学习总结-2020年12月16日
昨天把动画系统大致过了一遍,今天主要学习案例巩固,案例学习未完成,还是把一些操作总结以下。
一.lerp的使用
使用插值运算能够使得变化平滑,但是lerp插值的运算结果是无限趋近,无法到达,可以在插值后进行判断,插值结果和目标结果足够接近的化直接设置为目标结果。
siren.GetComponent<AudioSource>().volume = Mathf.Lerp(siren.GetComponent<AudioSource>().volume,0,Time.deltaTime * intensityChangeSpeed);
这是一段控制声音的代码,将音量设置为现有音量和0之间的插值,插值百分比为帧时间乘以每秒变化速度,可以将音量逐渐降为0,但是最后的结果无限趋近于0。可以作判断,如果当前音量和0的差小于0.01,则直接将音量设置为0,否则进行插值运算。
插值除了上面的线性插值外,还可以使用球形插值Slerp。线性插值和球形插值使用方法相同,达到的效果相似,但是底层的运算方法不同,球形插值会运算角度和向量长度。
二.pingpong的使用
使用pingpong方法能够使值在0和目标值之间来回变化,就像乒乓球一样。
alarmLight.intensity = Mathf.PingPong(Time.time * intensityChangeSpeed, 0.5f);
这是一段控制灯光强度的代码,使灯光强度在0和0.5之间来回变化,第一个参数为自递增的值,使用游戏运行时间。
三.单例模式
管理游戏进程和UI界面显示的脚本可以命名为GameManager(见下图,这个类名称为官方的类ID参考中的9号名称,将脚本修改为此名称脚本图标也会变成齿轮,谨慎使用)或者GameController等(随你乐意),这个类中的参数和方法等往往会被其他脚本设置或者调用,因此最好采用单例模式。
public static GameManager _instance; void Start() { _instance = this; }
见上面代码,在类中提供公开的静态的这个类的实例属性(一般可以命名为_instance),然后在初始化时将这个实例属性赋值,最好将构造方法私有化,这样在外部不能实例化这个类,而这个类自己提供了唯一的实例,因为是静态的,也可以在外部通过类名调用这个唯一实例。
四.标签类Tags
在游戏中,大量的游戏对象往往通过标签进行查找,在查找游戏对象时为了防止写错标签名,可以提供标签类Tags。
public class Tags : MonoBehaviour { public const string player = "Player"; public const string siren = "Siren"; public const string enemy = "Enemy"; }
标签类中使用const关键字修饰标签名称,可以在外部直接通过类名.属性名调用这个字符串(const是指静态且不可修改的变量),但是不能在外部修改属性的值。这里也可以使用枚举enum类,但是enum类的值是整数,这种方式更合适。
五.角色的动画和移动
角色的移动可以使用改变位移的方式,但是动画中也可以改变位移量(动画可以理解为在一定帧范围内,如0-60帧,游戏物体的位置、旋转、颜色等属性进行改变的过程),因此一般将位移直接做到动画中,播放动画人物模型也会相应的移动旋转等。
下面使用2D混合树控制角色的移动。
横轴的值代表角色的转向,纵轴的值代表角色的向前位移。从上到下四排分别对应跑、走、下蹲慢走、停止四种向前的状态,纵轴值对应1、0.5、0.25、0四种。从左到右三列对应向左转、没有方向改变、向右转,横轴值对应为-1、0、1三种。如走路并向左转为(-1,0.5),原地右转为(1,0)。接下来通过代码设置横轴和纵轴的值。
/// <summary> /// 获取键盘输入,并存储为h值和v值,以便update函数中用于设置animator的参数,使用插值运算使运动平滑 /// </summary> private void GetInputInfo() { //左shift键和向前键,下蹲慢走 if (Input.GetKey(KeyCode.LeftShift) && (Input.GetAxis("Vertical") > 0.1f)) { h = Mathf.Lerp(h,0f,acceleratedSpeed * Time.deltaTime);v = Mathf.Lerp(v, 0.25f, acceleratedSpeed * Time.deltaTime); } //向前向左和空格键,向左跑 else if(Input.GetAxis("Vertical") > 0.1f && Input.GetAxis("Horizontal") < -0.1f && Input.GetKey(KeyCode.Space)) { h = Mathf.Lerp(h, -1f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 1f, acceleratedSpeed * Time.deltaTime); } //向前向右键和空格键,向右跑 else if (Input.GetAxis("Vertical") > 0.1f && Input.GetAxis("Horizontal") > 0.1f && Input.GetKey(KeyCode.Space)) { h = Mathf.Lerp(h, 1f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 1f, acceleratedSpeed * Time.deltaTime); } //向前键和空格键,向前跑 else if (Input.GetAxis("Vertical") > 0.1f && Input.GetKey(KeyCode.Space)) { h = Mathf.Lerp(h, 0f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 1f, acceleratedSpeed * Time.deltaTime); } //向前向左键,向前走 else if (Input.GetAxis("Vertical") > 0.1f && Input.GetAxis("Horizontal") < -0.1f) { h = Mathf.Lerp(h, -1f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 0.5f, acceleratedSpeed * Time.deltaTime); } //向前向右键,向右走 else if (Input.GetAxis("Vertical") > 0.1f && Input.GetAxis("Horizontal") > 0.1f) { h = Mathf.Lerp(h, 1f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 0.5f, acceleratedSpeed * Time.deltaTime); } //向左键,原地左转 else if (Input.GetAxis("Horizontal") < -0.1f) { h = Mathf.Lerp(h, -1f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 0f, acceleratedSpeed * Time.deltaTime); } //=向右键,原地右转 else if (Input.GetAxis("Horizontal") > 0.1f) { h = Mathf.Lerp(h, 1f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 0f, acceleratedSpeed * Time.deltaTime); } //向前键,向前走 else if (Input.GetAxis("Vertical") > 0.1f) { h = Mathf.Lerp(h, 0f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 0.5f, acceleratedSpeed * Time.deltaTime); } //idle状态 else { h = Mathf.Lerp(h, 0f, acceleratedSpeed * Time.deltaTime); v = Mathf.Lerp(v, 0f, acceleratedSpeed * Time.deltaTime); } }
在update函数中调用这个函数,设置好h和v值后将animator组件中的horizontal参数和vertical参数的值同步为h和v值。这里使用了线性插值使运动状态的变化不会太突兀,也可以直接设置h和v值,这样动画播放切换的时候会有一些生硬。
void Update() { GetInputInfo(); anim.SetFloat("Vertical", v); anim.SetFloat("Horizontal", h); }
可以看到,这里并没有向后运动的动画,如果有可以继续添加,纵轴的值设置为负值即可,如有向右后方运动的动画设置坐标为(1,-1),再通过代码获取相应按键后设置h和v值即可。
ps:这种按键控制方式感觉对第一人称游戏的主角运动较为适用,而且一般主角运动默认都是跑步的,这里默认运动为走,不过也懒得修改了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!