zoukankan      html  css  js  c++  java
  • 学习总结-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:这种按键控制方式感觉对第一人称游戏的主角运动较为适用,而且一般主角运动默认都是跑步的,这里默认运动为走,不过也懒得修改了。

  • 相关阅读:
    内核开发特点
    制作 patch
    sdram flash 区别
    数组名 函数名
    Html标签见解——关于position问题分组总结
    Html标签见解——margin和padding使用过程中所谓的bug问题《一》
    HTML标签见解——img
    关于float和clear
    业内杂谈——你认识“用户体验”吗?
    css控制窗口上下水平居中方案详解
  • 原文地址:https://www.cnblogs.com/movin2333/p/14147506.html
Copyright © 2011-2022 走看看