首页 > 其他分享 >Unity之"诡异"的协程

Unity之"诡异"的协程

时间:2022-11-12 13:23:18浏览次数:66  
标签:诡异 协程 小车 Vector3 transform collision Unity 转弯

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

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

 

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

 

 

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

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

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

小车前进代码:

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);
    }

}

小车转弯代码:

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 调用中保持一致,所以这些局部作用域变量将被保存到上一级的生成的它们的类中,从而保证在协程的存活期内保留在堆上的地址分配。

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

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

房子的碰撞代码如下:

private void OnCollisionEnter(Collision collision)
    {
        if (this.CompareTag(collision.gameObject.tag))
        {
            GameController.Score++;
        }
        Destroy(collision.gameObject);
    }

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

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

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

这是不是很匪夷所思呢?

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

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

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

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

标签:诡异,协程,小车,Vector3,transform,collision,Unity,转弯
From: https://www.cnblogs.com/M-Anonymous/p/16883465.html

相关文章

  • 协程
    概念提示 协程不是进程也不是线程,而是一个特殊的函数。这个函数可以在某个地方被“挂起”,并且可以重新在挂起处外继续运行。所以说,协程与进程、线程相比并不是一个维度......
  • unity3d修改对象属性
    unity3d修改对象属性 #regionvoidloadWorkerModel(Vector3init_position,stringworker_name,stringBDID){GameObjectobj=(GameObject)......
  • Unity一键制作预制体Prefab一键修改Prefab属性
    1.适用于制作多个预制体(一个模型文件下面几百个子物体,都需要制作成预制体,这一个一个拖不是要炸裂)模型资源如下图 2.模型先放到Resources文件夹下面方便读取,制作......
  • 【Go】协程
    今天主要学习了一下go语言的多线程,也写了一些例子,最开始还是很困惑。比如下面这个例子:packagemainimport"fmt"funcloop(){fori:=0;i<10;i++{fmt.Printf("......
  • Unity 判断UI对象是否在屏幕内,并且把对象移进屏幕
    publicstaticboolJudgmentUiInScreen(GameObjectobj){RectTransformrect=obj.GetComponent<RectTransform>();RectTransformuiRoot=r......
  • 菜鸡学Unity 之 Unity中对游戏物体的常用操作旋转移动放缩
    LZ-Says:愿时光依旧,美好前方~前言本小节,我们一起来看下Unity中对游戏物体的常用操作旋转移动放缩这些基本骚操作吧~基本骚操作全程都可以简单操纵鼠标完成,当然,直接有效是......
  • unity 获取scene整体的bound包围盒以及center
    如下:多场景的情况也适合参考: https://gamedev.stackexchange.com/questions/134675/unity-bounds-includes-the-center-of-the-scene1privateList<Bounds>......
  • 协程 + epoll 的两个小例子
    getcontext/setupcontext/swapcontext/setcontext 方式的协程实现#include<stdio.h>#include<stdlib.h>#include<string.h>#include<poll.h>#include<errno.h>......
  • unity 对rotation、 localPosition、 localScale 进行修改
    unity对 rotation、localPosition、localScale进行修改 rotation:1、xxx.transform.localEulerAngles=newVector3(0.0f,0.0f,0.0f); 2、xxx.transform.rotat......
  • Unity描边的几种方式
    参考:在shader中实现五种描边方法从描边方式上来讲,大体可分为两种,一种是对着原模型往外扩大挤出,然后通过某种方式裁剪掉与原模型重合的地方,来实现描边。另一种则是通过算法......