Unity Animancer插件(三)运动

这篇具有很好参考价值的文章主要介绍了Unity Animancer插件(三)运动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、根运动

Animancer的根运动系统与原生的工作原理完全相同,但我们可以通过继承Transition类型或实现ITransition接口,来将额外的数据与动画绑定,从而更方便地控制根运动。

在下面这个示例中,我们通过自定义的Transition类实现动画根运动的灵活控制。
首先创建一个脚本RootMotion,并编写如下代码

// 自定义Transition类,将是否启用根运动封装
[Serializable]
public class MotionTransition:ClipTransition
{
	[SerializeField,Tooltip("是否启用根运动")]
	private bool applyRootMotion;

	// 在Play()时调用
	public override void Apply(AnimancerState state)
	{
		base.Apply(state);
		state.Root.Component.Animator.applyRootMotion = applyRootMotion;
	}
}

public class RootMotion : MonoBehaviour
{
	[SerializeField]
	private MotionTransition[] animations;
	[SerializeField]
	private AnimancerComponent animancer;

	private void OnEnable()
	{
		// 启用时播放第一段动画
		Play(0);
	}
	
	/// <summary>
	/// 播放指定动画
	/// </summary>
	/// <param name="index"></param>
	public void Play(int index)
	{
		animancer.Play(animations[index]);
	}
}

接下来给角色挂载这个脚本并指定两个动画,一个动画启用根运动,另一个不启用
Unity Animancer插件(三)运动

再通过UI动态控制角色播放的动画。看下效果
Unity Animancer插件(三)运动

当然,在Animancer中我们也可以通过OnAnimatorMove方法来控制根运动

[SerializeField] private Rigidbody rigid;
private void OnAnimatorMove()
{
	rigid.MovePosition(rigid.position+animancer.Animator.deltaPosition);
	rigid.MoveRotation(rigid.rotation*animancer.Animator.deltaRotation);
}

二、线性混合

通过Animancer,我们可以很方便地控制动画状态机进行播放。通过ControllerTransition可以接收一个动画状态机,并通过Animancer进行播放

public class LinearBlendTreeLocomotion : MonoBehaviour
{
	[SerializeField] private AnimancerComponent animancer;
	[SerializeField] private ControllerTransition controller;

	private void OnEnable()
	{
		animancer.Play(controller);
	}
}

但动画状态机中可能存在许多变量,并通过这些变量控制状态的切换或混合。比如下面的混合树
Unity Animancer插件(三)运动

对于这种情况,Animancer提供了封装好参数的ControllerTransition类型。上面的混合树只需要一个float类型的参数Speed,所以我们可以直接通过如下方式对参数进行控制

public class LinearBlendTreeLocomotion : MonoBehaviour
{
	[SerializeField] private AnimancerComponent animancer;
	[SerializeField] private Float1ControllerTransition controller;

	private void OnEnable()
	{
		animancer.Play(controller);
	}
	
	// 设置Speed参数
	public float Speed
	{
		set => controller.State.Parameter = value;
		get => controller.State.Parameter;
	}
}

在Inspector面板中可以对参数进行绑定
Unity Animancer插件(三)运动

接下来,我们可以通过一个Slider对Speed属性进行控制,效果如下
Unity Animancer插件(三)运动

如果有许多角色应用了相同的动画状态机和参数,我们也不必为每个角色单独设置。只需要将前面的Float1ControllerTransition更改为Float1ControllerTransitionAsset.UnShared类型,就可以直接指定一个配置文件。
右键「Create -> Animancer -> Controller Transition -> Float 1」创建一个配置文件,然后对其中的属性赋值。
Unity Animancer插件(三)运动

接下来就可以复用这个配置文件了,将其拖拽到相应的位置即可。
Unity Animancer插件(三)运动

也可以抛弃动画状态机,完全使用Animancer封装好的混合树(在Animancer中叫混合器)。混合器本质上就是在运行时构建的混合树。它的使用方法如下

public class LinearBlendTreeLocomotion : MonoBehaviour
{
	[SerializeField] private AnimancerComponent animancer;
	[SerializeField] private LinearMixerTransition controller;

	private void OnEnable()
	{
		animancer.Play(controller);
	}
	
	// 设置权重
	public float Speed
	{
		set => controller.State.Parameter = value;
		get => controller.State.Parameter;
	}
}

只是将前面代码中的ControllerTransition类型换成了LinearMixerTransition。通过改变其中的参数可以控制动画的权重,从而实现混合效果。接下来只需要在Inspector面板中指定动画即可。注意:对于Idle这种动画应该关闭Sync选项。Sync是为了同步每个状态的时间,以解决两个状态混合时动作错位的问题(比如walk动画左脚迈出,run动画右脚迈出,此时两个动画混合会产生问题)。但一般情况下Idle动画会比walk或run动画时间长的多,此时如果开启时间同步,就会导致walk动画播放速度慢很多。
Unity Animancer插件(三)运动

演示效果与前面相同,这里不再赘述。

三、定向混合

除了前面的1D混合树效果,Animancer也可以通过MixerTransition2D实现2D混合树的效果。

下面我们来通过MixerTransition2D实现一个机器人跟随鼠标移动的效果。首先将之前写过的SpiderBot脚本拿过来,将move的类型替换为MixerTransition2D

public class SpiderBot2 : MonoBehaviour
{
	public AnimancerComponent animancer;
	public ClipTransition wakeUp;
	// 将原本的ClipTransition替换为MixerTransition2D
	public MixerTransition2D move;
	private bool _isMoving;

	public bool IsMoving
	{
		get => _isMoving;
		set
		{
			if (value)
				WakeUp();
			else
				GoToSleep();
		}
	}
	
	/// <summary>
	/// 睡眠
	/// </summary>
	private void GoToSleep()
	{
		if (!_isMoving) return;
		_isMoving = false;
		// 反向播放Wake Up动画
		var state = animancer.Play(wakeUp);
		state.Speed = -1;

		if (state.Weight == 0 || state.NormalizedTime > 1)
		{
			state.NormalizedTime = 1;
		}
	}

	/// <summary>
	/// 唤醒
	/// </summary>
	private void WakeUp()
	{
		if (_isMoving) return;
		_isMoving = true;
		// 正向播放Wake Up动画
		var state = animancer.Play(wakeUp);
		state.Speed = 1;

		animancer.Playable.UnpauseGraph();
	}

	private void Awake()
	{
		animancer.Play(wakeUp);
		// 暂停整个图
		animancer.Playable.PauseGraph();
		// 计算第一帧
		animancer.Evaluate();

		wakeUp.Events.OnEnd = OnWakeUpEnd;
	}

	private void OnWakeUpEnd()
	{
		// 速度大于0时唤醒
		if (wakeUp.State.Speed > 0)
		{
			animancer.Play(move);
		}
		// 否则是睡眠
		else
		{
			animancer.Playable.PauseGraph();
		}
	}
}

将这个脚本挂载到机器人身上,即可在Inspector面板中看到2D混合树界面
Unity Animancer插件(三)运动

接下来编写机器人的移动脚本SpiderBotController

public class SpiderBotController : MonoBehaviour
{
	[SerializeField] private SpiderBot2 spider;
	[SerializeField] private Rigidbody body;
	// 移动速度
	[SerializeField] private float moveSpeed;
	// 旋转速度
	[SerializeField] private float rotateSpeed;
	// 加速倍率
	[SerializeField] private float sprintMultiplier;

	// 2D混合器
	private MixerState<Vector2> _moveState;
	// 移动方向
	private Vector3 _moveDir;

	private void Awake()
	{
		// 获取混合器
		var state = spider.animancer.States.GetOrCreate(spider.move);
		_moveState = (MixerState<Vector2>) state;
	}
	
	/// <summary>
	/// 获取移动方向
	/// </summary>
	/// <returns></returns>
	private Vector3 GetMoveDir()
	{
		// 射线检测
		var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		
		if (!Physics.Raycast(ray, out RaycastHit hit))
			return default;
		// 移动方向
		var dir = hit.point - transform.position;
		dir.y = 0;
		// 一帧移动的距离
		var movementThisFrame = moveSpeed * sprintMultiplier * Time.fixedDeltaTime;
		var distance = dir.magnitude;
		// 目标距离小于一帧移动的距离,则返回zero
		if (distance <= movementThisFrame)
			return default;
		return dir.normalized;
	}

	private void Update()
	{
		_moveDir = GetMoveDir();
		spider.IsMoving = _moveDir != default;
		
		if (_moveState.IsActive)
		{
			// 旋转
			var eulerAngles = transform.eulerAngles;
			var targetEulerY = Camera.main.transform.eulerAngles.y;
			eulerAngles.y = Mathf.MoveTowardsAngle(eulerAngles.y, targetEulerY, rotateSpeed * Time.deltaTime);
			transform.eulerAngles = eulerAngles;
			
			// 设置混合器参数
			_moveState.Parameter = new Vector2(
				Vector3.Dot(transform.right, _moveDir),
				Vector3.Dot(transform.forward, _moveDir));
			
			// 鼠标左键按下奔跑
			var isSprinting = Input.GetMouseButton(0);
			_moveState.Speed = isSprinting ? sprintMultiplier : 1;
		}
		else
		{
			// 混合器未激活,将速度和参数归零
			_moveState.Parameter = default;
			_moveState.Speed = 0;
		}
	}

	private void FixedUpdate()
	{
		// 利用刚体移动
		body.velocity = _moveState.Speed * moveSpeed * _moveDir;
	}
}

看下效果
Unity Animancer插件(三)运动

四、参考资料

[1]. https://kybernetik.com.au/animancer/docs/examples/locomotion/文章来源地址https://www.toymoban.com/news/detail-497736.html

到了这里,关于Unity Animancer插件(三)运动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity Fungus插件的对话系统简单使用

    Fungus是Unity免费的一款开源的插件,它可以无代码的实现玩家与NPC之间的对话,对于Fungus这个插件,我今天说一说我对它的看法以及一些简单的运用和简单的代码功能的实现。 这里需要导入Fungus插件,插件导完之后会出现Tools/Fungus   SayDialog模板使用,Menu菜单选项,Character玩

    2024年02月09日
    浏览(48)
  • Unity 音频插件 - MasterAudio 实现音频管理系统

    插件介绍: Master Audio的是一个整体解决方案,所有的丰富的游戏音频需求。内置的音乐闪避,手动和自动的声音触发真正的随机声音变化,音频汇集全3D声音功能。支持所有出口的手机游戏平台,具有一流的性能。 主音频在线帮助网站可在此处找到: Table of Contents 完整的 主

    2023年04月10日
    浏览(48)
  • 新手向 使用C#自带方法制作unity存档系统(无插件)

    纯原创,自制 本人还是个在校的高中生,能力不精如果有漏洞欢迎指出 先放出我们示范项目的样子 演示项目工程文件下载 后面会在B站发详细的视频教程(所以文章之后肯会改) 嫌麻烦的直接复制到项目里就可以用哦 (全部的SaveSystem源码最后放出方便大家复制) 可以存储

    2024年02月10日
    浏览(54)
  • unity库存系统插件-Ultimate Inventory System(一)功能简介

    如果说一个rpg游戏必不可少的功能,那就必须想到背包、商店、宝箱、交易、物品栏这些,我们可以将其统称为库存系统。可以说哪怕非rpg游戏也有库存系统的需求。 本文将使用 Ultimate Inventory System 插件快速实现库存系统,抛弃掉繁杂冗余的编程开发,快速实现游戏原型(主

    2024年01月20日
    浏览(45)
  • unity3d 布娃娃系统插件 PuppetMaster 木偶师

    PuppetMaster包含一个非常易于使用的视觉布娃娃创建工具,用于人形角色,将角色的动画的姿势映射到木偶的的肌肉使其同步,并保持在那里,直到动画在下一帧覆盖它。   1. 将 人形 角色模型拖动到场景并附加 BipedRagdollCreator . cs 组件。点击 “Create a Ragdoll” 按钮 , 点击 “ D

    2023年04月08日
    浏览(90)
  • 【一步步开发AI运动小程序】二、引入插件

    随着人工智能技术的不断发展,阿里体育等IT大厂,推出的“乐动力”、“天天跳绳”AI运动APP,让 云上运动会、线上运动会、健身打卡、AI体育指导 等概念空前火热。那么,能否将这些在APP成功应用的场景搬上小程序,分享这些概念的红利呢?本系列文章就带您一步一步从

    2024年02月05日
    浏览(39)
  • Unity 使用按键控制角色运动

    创建角色 创建一个脚本PlayerController 创建控制器,使用boolean值        脚本 然后我们运行时还是会感觉有一点过渡衔接不自然,我们可以更改动画器参数里的设置    当然设为0的话是没有过渡的动画,类似于硬直,所以按照自己的意愿来调试。

    2024年02月12日
    浏览(43)
  • Unity 物体的运动之跟随鼠标

            你想让鼠标点击哪里,你的运动的对象就运动到哪里吗? Please follow me ! 首先,你要先添加一个Plane ,以及你的围墙,你的移动的物体   想要实现跟随鼠标移动,我们先创建一个脚本 先简单的分析一下代码: 开始的时候应该先创建一个空物体,将该空物体拉进去脚

    2024年02月12日
    浏览(86)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包