• 学习总结-2020年12月18日


    一.自动门的制作

      首先将门模型挂载在一个空物体下,模型需要挂载一个collider,使门具有物理属性,玩家不能穿过,这个collider不能挂载到空物体上,它需要能随着门一起移动,接下来通过动画或者脚本实现门的开合。在挂载了模型的空物体上添加一个collider组件,一般是球形碰撞器,设置为trigger类型,用于检测玩家是否走入门的范围。

    private void OnTriggerEnter(Collider other)
        {
            if (other.tag == Tags.enemy || other.tag == Tags.player)
                count++;
        }
        private void OnTriggerExit(Collider other)
        {
            if (other.tag == Tags.enemy || other.tag == Tags.player)
                count--;
        }

      使用一个计数器count记录走入的门碰撞体内的玩家数目。

    private void Update()
        {
            if(count > 0)
            {
                anim.SetBool("IsDoorOpen", true);
            }
            else
            {
                anim.SetBool("IsDoorOpen",false);
            }
    
            if (anim.IsInTransition(0) && !doorAudio.isPlaying)
            {
                doorAudio.Play();
            }
        }

      在update函数中更新动画参数,如果检测到门周围玩家数大于0,播放门开启动画,如果检测到周围玩家数为0则播放门关闭动画。同时门在开启和关闭过程中播放动画音效。

    二.物体在被拾起时的动画音效播放

      物品在被拾起时需要销毁物品,这时如果采用Audio Source组件播放音效,组件会随着物品一同被销毁,音效实际上没有播放,采用静态方法AudioSource.PlayClipAtPoint播放音效就能避免这个问题。

    public AudioClip video_pickup;
        private void OnTriggerEnter(Collider other)
        {
            if(other.tag == Tags.player)
            {
                Player._instance.hasKey = true;
                AudioSource.PlayClipAtPoint(video_pickup, transform.position);
                Destroy(gameObject);
            }
        }

    三.简单的镜头跟随

      通过保持镜头和玩家的偏移不变使镜头始终跟随玩家。

        //记录镜头的偏移
        private Vector3 offset;
        //镜头的跟随对象
        public Transform player;
    
        private void Start()
        {
            //初始化偏移量
            offset = player.position - transform.position;
            //修正偏移量,使跟随对象始终在镜头中间位置,这个根据具体的镜头和跟随对象的相对位置确定怎么修正,不修正也没关系
            offset.x = 0;
        }
        private void Update()
        {
            //始终使镜头位置和跟随对象的偏移量保持一致
            //这个计算和初始化偏移量的计算是互为逆运算,初始化时镜头位置为减数,这里用被减数减去差计算,如果是被减数则采用减数加差(好基础的问题,但还是想记录下来)
            transform.position = player.position - offset;
        }

    四.解决视野的盲区  

      镜头跟随的情况下可能产生视角的盲区,因此可以通过射线检测得到镜头一个合适位置。

      首先修改偏移量计算方式,这样设置计算摄像机的合适位置更简单一些。

         //初始化偏移量
            offset = transform.position - player.position;

      然后计算并设置镜头的位置

       /// <summary>
        /// 检测得到合适的镜头位置,并采用插值运算的方式设置好镜头的位置
        /// </summary>
        private void SetCameraTransform()
        {
            //计算并记录可以用于检测的位置,即可能的摄像机位置
            //位于玩家正上方的位置
            Vector3 position0 = player.position + offset.magnitude * Vector3.up;
            //当前镜头位置
            Vector3 position4 = player.position + offset;
            //插值运算得到镜头和玩家的中间的可能位置
            Vector3 position1 = Vector3.Slerp(position0, position4, 0.25f);
            Vector3 position2 = Vector3.Slerp(position0, position4, 0.5f);
            Vector3 position3 = Vector3.Slerp(position0, position4, 0.75f);
            
            
            //最终找到的合适的摄像机位置
            Vector3 suitablePosition = position4;
    
            //用一个数组记录可能的摄像机位置
            Vector3[] positions = new Vector3[] { position0, position1, position2, position3, position4 };
    
            //倒序遍历数组,记录下可能的摄像机位置
            for(int i = 4;i >= 0;i--)
            {
                //射线检测
                RaycastHit hit;
                if(Physics.Raycast(positions[i], player.position - positions[i], out hit))
                {
                    //如果射线第一个碰撞的不是玩家,代表玩家和摄像机之间有遮挡,这个位置不可用
                    if(hit.transform.tag != Tags.player)
                    {
                        continue;
                    }
                    //如果射线第一个遇到的碰撞体是玩家,则这个位置为可用的位置,找到了合适的位置就可以也必须直接结束循环了
                    else
                    {
                        suitablePosition = positions[i];
                        break;
                    }
                }
                //意外情况下,射线未检测到任何碰撞体,还是将当前位置作为合适的位置
                else
                {
                    suitablePosition = positions[i];
                    break;
                }
            }
    
            //通过插值使摄像机平滑运动到合适的位置
            transform.position = Vector3.Slerp(transform.position, suitablePosition, Time.deltaTime * cameraMoveSpeed);
            //摄像机也需要望向玩家,通过插值运算使摄像机平滑旋转
            Quaternion nowRotation = transform.rotation;
            transform.LookAt(player.position);
            transform.rotation = Quaternion.Slerp(nowRotation, transform.rotation, Time.deltaTime);
        }

      最后在update中调用这个方法

    private void Update()
        {
            SetCameraTransform();
        }
  • 相关阅读:
    web----WSGI
    ovs 实现vlan隔离(一)
    ovs流表机制(四)用vxlan实现不同网段通信
    ovs流表机制(四)用vxlan实现同网段通信
    ovs 流表机制(三)--group表
    ovs 流表机制(二)-OVS流表table之间的跳转
    ovs 流表机制(一)
    euler ironic镜像驱动问题(一)镜像启动失败报dracut initqueue timeout
    ovs流表
    arm64 uefi启动
  • 原文地址:https://www.cnblogs.com/movin2333/p/14154126.html
Copyright © 2020-2023  润新知