Maxime FRAPPAT

Hum …no thanks ! – Lordinaire

Tag: unity (Page 2 of 6)

[Unity] Replay the same animation during its execution

When you use animators and animations in your game, you may want to be able to play an animation even if it’s already running.

To explain how to do this, we will create a scene with a simple square object. This square will have an animator component attached to it.

With transition

You can achieve an animation with transition by playing it with the CrossFade method.

Let’s create a new animation like this one :

animation_with_transition

Add a new C# script component attached to the cube object :

public class MoveBehavior : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 70, 50, 30), "Replay"))
        {
            var animator = GetComponent<Animator>();
            animator.CrossFade("Move", 1f);
        }
    }
}

If you play the scene and click on the “Replay” button, the animation will start.

Notice that if you click on the button again between 0 and 1 second, the animation will start transition, but if you click between 1 and 2 seconds nothing will happen. It’s because our animation during 2 seconds and we set the fading length to 1 second. To be able to play a transition all along the animation, set the fading length to 2 seconds.

Without transition

Unlike the CrossFade method, the Play method will not rewind to the beginning. So, if you want to replay an animation you can use a little trick.

Create your animation in two parts. The first part need to be a one-frame animation :

first_animation_without_transition

The second part is the “real” animation :

second_animation_without_transition

Edit the script with those snippet :

public class MoveBehavior : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 70, 50, 30), "Replay"))
        {
            var animator = GetComponent<Animator>();
            animator.Play("BeginMove");
        }
    }
}

By playing the BeginMove animation, it will transition to the EndMove after only one frame. So, if you play again BeginMove after 1 second, the animator current animation will be EndMove so you will be able to replay the animation to the beginning :)

Have fun !

[Unity] Custom build for WP8/W8

If your game target the Windows Phone 8 or Windows Store platform, you probably want to use some specific feature like the share, live tiles, …

This can be done by using some tricks that I already explain in a previous thread (http://blog.lordinaire.fr/2014/09/unity-interact-between-unity-and-windows-phone-8-windows-store-apps/) but I might be pretty cool to build automatically custom files like splashscreen, MainPage or tiles.

Create a specific menu item

The first step is to create a menu item to easily access to our build.

using System.Linq;
using System.Security.Policy;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System;

public class AutoBuilderMenu : MonoBehaviour
{
	[MenuItem("AutoBuilder/WP8")]
	private static void PerformBuild()
	{
		// TODO : Build and replace files
	}
}

For more information about MenuItem see http://blog.lordinaire.fr/2014/10/unity-create-custom-menu-items/

Simple build

using System.Linq;
using System.Security.Policy;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System;

public class AutoBuilderMenu : MonoBehaviour
{
	[MenuItem("AutoBuilder/WP8")]
	private static void PerformBuild()
	{
		// Save current editor build target
		var currentTarget = EditorUserBuildSettings.activeBuildTarget;
		EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.WP8Player);

		var buildPath = GetBuildPath(target);
		var path = Path.GetDirectoryName(buildPath);

		var folderExists = Directory.Exists(path);
		if (!folderExists)
			Directory.CreateDirectory(path);

		// Create solution folder and project files
		BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None);

		// Set saved build target
		EditorUserBuildSettings.SwitchActiveBuildTarget(currentTarget);
	}

	private static string GetProjectName()
	{
		string[] s = Application.dataPath.Split('/');
		return s[s.Length - 2];
	}

	private static string[] GetScenePaths()
	{
		return EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray();
	}

	private static string GetBuildPath(BuildTarget target)
	{
		var extension = String.Empty;

		return String.Format("../Builds/{0}/{1}/{2}/{3}",
			GetProjectName(),
			PlayerSettings.bundleVersion,
			target.ToString(),
			PlayerSettings.bundleIdentifier);
	}
}

The project will be create in the folder ../Builds/{ProjectName}/{BundleVersion}/{TargetPlatform}/{BundleIdentifier} so we have a build for each version of our game in a specific folder.

Custom build

using System.Linq;
using System.Security.Policy;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System;

public class AutoBuilderMenu : MonoBehaviour
{
	[MenuItem("AutoBuilder/WP8")]
	private static void PerformBuild()
	{
		// Save current editor build target
		var currentTarget = EditorUserBuildSettings.activeBuildTarget;
		EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.WP8Player);

		var buildPath = GetBuildPath(target);
		var path = Path.GetDirectoryName(buildPath);

		var folderExists = Directory.Exists(path);
		if (!folderExists)
			Directory.CreateDirectory(path);

		// First build to create solution folder and project files
		BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None);

		// Replace custom files
		UpdateWP8Settings(buildPath);

		// Rebuild with replacing files
		BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None);

		// Set saved editor build target
		EditorUserBuildSettings.SwitchActiveBuildTarget(currentTarget);
	}

	private static void UpdateWP8Settings(string buildPath)
	{
		// SplashScreenImage
		var replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/SplashScreenImage.jpg");
		var current = string.Format("{0}/{1}/SplashScreenImage.jpg", buildPath, PlayerSettings.bundleIdentifier);
		if (File.Exists(replace))
			File.Copy(replace, current, true);

		// MainPage.xaml.cs
		replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/MainPage.xaml.cs");
		current = string.Format("{0}/{1}/MainPage.xaml.cs", buildPath, PlayerSettings.bundleIdentifier);
		if (File.Exists(replace))
			File.Copy(replace, current, true);		

		// ApplicationIcon
		replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/ApplicationIcon.png");
		current = string.Format("{0}/{1}/Assets/ApplicationIcon.png", buildPath, PlayerSettings.bundleIdentifier);
		if (File.Exists(replace))
			File.Copy(replace, current, true);

		// WMAppManifest
		replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/WMAppManifest.xml");
		current = string.Format("{0}/{1}/Properties/WMAppManifest.xml", buildPath, PlayerSettings.bundleIdentifier);
		if (File.Exists(replace))
			File.Copy(replace, current, true);
	}

	private static string GetProjectName()
	{
		string[] s = Application.dataPath.Split('/');
		return s[s.Length - 2];
	}

	private static string[] GetScenePaths()
	{
		return EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray();
	}

	private static string GetBuildPath(BuildTarget target)
	{
		return String.Format("../Builds/{0}/{1}/{2}/{3}",
			GetProjectName(),
			PlayerSettings.bundleVersion,
			target.ToString(),
			PlayerSettings.bundleIdentifier);
	}
}

The trick is to build twice the game. First we build to create all files then we replace our custom files and we rebuild to use these new files.

A more elegant way

private static void PerformBuild(BuildTarget target, bool isBeta = false)
{
	var currentTarget = EditorUserBuildSettings.activeBuildTarget;
	EditorUserBuildSettings.SwitchActiveBuildTarget(target);

	var buildPath = GetBuildPath(target);
	var path = Path.GetDirectoryName(buildPath);

	var folderExists = Directory.Exists(path);
	if (!folderExists)
	{
		Directory.CreateDirectory(path);
	}

	BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None);

	if (target == BuildTarget.WP8Player)
	{
		UpdateWP8Settings(buildPath, string.Concat(Application.dataPath, "/../BuildSettings/WP8/"), string.Concat(buildPath, "/"));
		if (isBeta)
		{
			UpdateWP8Settings(buildPath, string.Concat(Application.dataPath, "/../BuildSettings/WP8_Beta/"), string.Concat(buildPath, "/"));

		}
		BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None);
	}

	EditorUserBuildSettings.SwitchActiveBuildTarget(currentTarget);
}

private static void UpdateWP8Settings(string buildPath, string sourceRootPath, string destinationRootPath = "")
{
	var files = Directory.GetFiles(sourceRootPath);
	foreach (var file in files)
	{
		var replace = file;
		var fileName = replace.Split('/').LastOrDefault().Split('\\').LastOrDefault();
		var current = string.Concat(destinationRootPath, "/" + fileName);
		File.Copy(replace, current, true);
	}

	var directories = Directory.GetDirectories(sourceRootPath);
	foreach (var directory in directories)
	{
		var folderName = directory.Split('/').LastOrDefault().Split('\\').LastOrDefault();
		UpdateWP8Settings(buildPath, directory, destinationRootPath + "/" + folderName);
	}
}

You just need to add all your files in the folder BuildSettings/WP8 and/or BuildSettings/WP8_Beta with the same hierarchy as the project and it’s done ! Thanks Jonathan for the tips ;)

unity_custom_build

It’s the same way with Windows Store apps :)

Page 2 of 6

Powered by WordPress & Theme by Anders Norén

%d bloggers like this: