• Unity之"诡异"的协程


    为什么说是诡异的协程呢?首先从一个案例说起吧,示例如下:

    游戏目标:让小车进入到对应颜色屋子里,即可获得一分。(转弯的道路可控)

     

    为了让小车能够平滑转弯,小车的前进方向需要和车子的位置与圆心组成的连线垂直。

     

     

    首先想到的就是在车子进入到碰撞体和在碰撞体里面都是上述运动方式,离开碰撞体后相当于旋转了90度。

    但是当车子在转弯的道路上时,此时将左转弯的路变成右转弯的路,车子就会失控,因为碰撞体消失后对应的事件就不会执行了。

    所以想到让车子持续转弯的方法放进协程里面做,小车前进代码和转弯代码如下:

    小车前进代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class CarMove : MonoBehaviour
    {
        public float Speed = 1f;
     
        // Start is called before the first frame update
        void Start()
        {
             
        }
     
        // Update is called once per frame
        void Update()
        {  
            transform.Translate(Vector3.forward * Speed * Time.deltaTime);
        }
     
    }

    小车转弯代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    public class CurveCollider : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
             
        }
     
        // Update is called once per frame
        void Update()
        {
             
        }
     
        private void OnCollisionEnter(Collision collision)
        {
            if (this.CompareTag("TurnLeft"))
            {
                StartCoroutine(CarTurnLeft(collision));
            }
        }
     
        IEnumerator CarTurnLeft(Collision collision)
        {
            while (true)
            {
                Vector3 worldUp = Vector3.up;
                Vector3 targetPos = collision.transform.position;
                Vector3 direction = transform.position - targetPos;
                Vector3 forwardDir = new Vector3(-1.0f, 1.0f, 1.0f);
                Vector3.OrthoNormalize(ref worldUp, ref direction, ref forwardDir);
                Quaternion quaternion = Quaternion.identity;
                quaternion.SetLookRotation(forwardDir);
                collision.transform.rotation = quaternion;
                yield return null;
                Debug.Log(collision.transform.eulerAngles.y);
                if (collision.transform.eulerAngles.y >= 270 && (collision.transform.eulerAngles.y - 270) <= 1)
                {
                    quaternion = Quaternion.identity;
                    quaternion.eulerAngles = new Vector3(0.0f, -90.0f, 0.0f);
                    collision.transform.rotation = quaternion;
                    yield break;
                }
            }
        }
    }

    下面先简单介绍一下协程的基本概念:Unity手册:协程
    UnityEngine所提供的SDK都只能在单线程中调用,而协程也是单线程的,不同于多线程。

    Unity中只代码只要有一个地方代码出现死循环或者运行时间较长,游戏就会卡死。

    关于协程其中有这么一句话,很重要:协程优化

    因为协程中的局部作用域变量必须在 yield 调用中保持一致,所以这些局部作用域变量将被保存到上一级的生成的它们的类中,从而保证在协程的存活期内保留在堆上的地址分配。

    好了,现在回到我们的案例,发生了什么问题呢?

    当其中一个小车进入到房子后,其中有一个小车没有正常转弯了,并且发生报错,如上图标红的地方,这是为什么呢?

    房子的碰撞代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    private void OnCollisionEnter(Collision collision)
        {
            if (this.CompareTag(collision.gameObject.tag))
            {
                GameController.Score++;
            }
            Destroy(collision.gameObject);
        }

    当小车进入到房子后就会摧毁小车,如果进入的车是对的,就加一分。

    报错的行43行是如下代码:

    1
    if (collision.transform.eulerAngles.y >= 270 && (collision.transform.eulerAngles.y - 270) <= 1) 

    这是不是很匪夷所思呢?

    因为当小车进入直线轨道时协程已经结束了,怎么协程还在运行呢?

    此时你可以想起上面那句话,应该可以猜到了为什么会发生这样。

    当Car1进入House碰撞体时,也将Collider存放在同一个地方,之后将这个小车摧毁。

    此时小车3正好在执行协程,当从yield 之后的语句开始执行时,由于小车已经被摧毁,所以就报错了。

    仿照Lumosity中的一款小火车游戏,小火车恰好在来回变换的轨道上,此时正常前进或平滑转弯是个挺难的地方,暂无实现思路。

  • 相关阅读:
    如何通过手机自学编程入门:探索四、五、六、七方面的学习路径
    Linux中_Ubuntu上_安装Windows软件_微信_企业微信_等
    计算机毕业设计之java+ssm基于微信小程序的游戏美术外包管理信息系统
    [管理与领导-103]:IT经营者、管理者与所有者的关系
    搜索技术【广度优先搜索】 - 队列式广度优先搜索
    如何在spark中使用scikit-learn和tensorflow等第三方python包
    【Java面试】为什么重写equals方法必须同时重写HashCode方法?
    线性回归(概念+实例)
    【漏洞复现】panalog日志审计系统任意用户创建漏洞和后台命令执行
    数据可视化在商业领域有哪些重要性?
  • 原文地址:https://www.cnblogs.com/M-Anonymous/p/16883465.html