Unity C#问题:父物体旋转时LookAt函数产生异常结果
3D立方体表面贪吃蛇:蛇段旋转异常问题
我是编程新手,主要靠Unity和C#学习游戏开发,目前在做一款3D贪吃蛇——玩家不是在2D平面,而是在立方体表面移动。
我写了代码让蛇身段转向时自动旋转,保证模型朝向正确:蛇头脚本用LookAt函数,让视觉模型的背部朝向刚离开的点位。正常情况下功能没问题,但只要玩家转向新面导致立方体旋转,所有蛇段的角度就会变得异常,LookAt的目标Vector3和传入的点位置完全对不上。
我测试过,哪怕蛇段完全不动,只旋转立方体,也会出现同样的问题;后来试着用相机绕立方体移动替代立方体旋转,问题还是没解决。我希望蛇段能看向立方体前一面的上一个点,怀疑是角度计算用了局部空间而非世界空间,但一直没找到解决办法,而且我对Quaternions相关知识也不太熟悉。
以下是蛇头的代码:
public GameObject ourPoint; public GameObject thisPoint; public GameObject playerSegmentPrefab; public List<GameObject> segments; public float secondsSinceLastMovement; public float timeBetweenMovements; public int direction; public bool pointsSet = false; [SerializeField] private GameObject playerVisual; [SerializeField] private Vector3 lookAtTarget; [SerializeField] private GameObject a; public bool test; // Start is called before the first frame update void Awake() { References.player = this; direction = 4; lookAtTarget = new Vector3(0, -5, -1.5f); } void Start() { GameObject firstSegement = Instantiate(playerSegmentPrefab, transform.position, transform.rotation); segments.Insert(0, firstSegement); firstSegement.transform.SetParent(gameObject.transform); GameObject secondSegment = Instantiate(playerSegmentPrefab, transform.position, transform.rotation); segments.Insert(1, secondSegment); secondSegment.transform.SetParent(gameObject.transform); Player_Segment_Behaviour firstSegmentScript = firstSegement.GetComponent<Player_Segment_Behaviour>(); firstSegmentScript.follower = secondSegment; } void Move(int upDownRightLeft) { int currentPeak = References.ground.peak; int currentFace = References.ground.face; Point_Script ourPointScript = ourPoint.GetComponent<Point_Script>(); if(upDownRightLeft == 1) { thisPoint = ourPointScript.upPoint; } if(upDownRightLeft == 2) { thisPoint = ourPointScript.downPoint; } if(upDownRightLeft == 3) { thisPoint = ourPointScript.rightPoint; } if(upDownRightLeft == 4) { thisPoint = ourPointScript.leftPoint; } Point_Script thisPointScript = thisPoint.GetComponent<Point_Script>(); if(thisPoint != null) { if(ourPointScript.ourCube == thisPointScript.ourCube) { References.ground.face = thisPointScript.compass; } } Player_Segment_Behaviour firstSegmentScript = segments[0].GetComponent<Player_Segment_Behaviour>(); firstSegmentScript.Move(ourPoint, upDownRightLeft, thisPoint); lookAtTarget = ourPoint.transform.position; ourPoint = thisPoint; if(thisPointScript.ourCube == ourPointScript.ourCube) { References.ground.ChangeTarget(upDownRightLeft); } secondsSinceLastMovement = 0; if(test == false) { playerVisual.transform.LookAt(lookAtTarget); } } // Update is called once per frame void Update() { playerVisual.transform.LookAt(lookAtTarget); if(test == true) { lookAtTarget = a.transform.position; } for(int i = 0; i < segments.Count; i ++) { if(segments[i] != null) { Player_Segment_Behaviour thisSegment = segments[i].GetComponent<Player_Segment_Behaviour>(); thisSegment.test = test; thisSegment.a = a; } } if(References.ground.points.Count >= 149 && pointsSet == false) { Player_Segment_Behaviour firstSegmentScript = segments[0].GetComponent<Player_Segment_Behaviour>(); Player_Segment_Behaviour secondSegmentScript = segments[1].GetComponent<Player_Segment_Behaviour>(); Point_Script ourPointScript = ourPoint.GetComponent<Point_Script>(); firstSegmentScript.ourPoint = ourPointScript.downPoint; firstSegmentScript.gameObject.transform.position = ourPointScript.downPoint.transform.position; Point_Script firstSegementPointScript = firstSegmentScript.ourPoint.GetComponent<Point_Script>(); secondSegmentScript.ourPoint = firstSegementPointScript.downPoint; secondSegmentScript.gameObject.transform.position = firstSegementPointScript.downPoint.transform.position; pointsSet = true; } transform.position = ourPoint.transform.position; secondsSinceLastMovement += Time.deltaTime; if(References.ground.cycleActive == false) { if(Input.GetKeyDown(KeyCode.A) && direction != 3) { direction = 4; Move(direction); } if(Input.GetKeyDown(KeyCode.D) && direction != 4) { direction = 3; Move(direction); } if(Input.GetKeyDown(KeyCode.W) && direction != 2) { direction = 1; Move(direction); } if(Input.GetKeyDown(KeyCode.S) && direction != 1) { direction = 2; Move(direction); } if(secondsSinceLastMovement >= timeBetweenMovements) { Move(direction); } } }
(test布尔值用于测试蛇段朝向,通过GameObject a作为目标调整模型对齐)
内容的提问来源于stack exchange,提问作者Matthew Brady
相关产品推荐
相关产品推荐

