如何修复 Unity 中的痉挛和错误实例化

How to fix spasming and buggy instantiation in Unity

我正在用 C# 在 Unity 中创建一个基本台球游戏,我想做的是如果母球在移​​动,球杆就会消失,一旦它再次静止,它就会重新出现在球杆所在的位置母球位于。到目前为止,这是我的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class stickDeplacement : MonoBehaviour
{
    public bool bIsOnTheMove = false;
    Vector3 lastPos;
    public GameObject Stick;

    void Start()
    {

    }


    void Update()
    {
        var stick = Instantiate(Stick, gameObject.transform.position, gameObject.transform.rotation);
        if (this.transform.position != lastPos)
        {
            Destroy(stick);
            Debug.Log("Is moving");
        }
        else
        {
            Debug.Log("Is not moving");
        }

        lastPos = this.transform.position;

    }


}

但实际情况是,球和棍子从一开始(当我打开并玩游戏时)就会痉挛并出现故障。我在这里遗漏了什么吗?

  • 这是极其低效和危险的!

    为什么 每一帧 实例化一根棍子只是为了最终在同一帧中摧毁它?如果球是静止的,您希望每帧都生成一根额外的棍子?

    与其一直实例化和销毁它,不如保留 one 并仅(取消)激活它。

    在您的情况下,您可以在一行中完成此操作

    bIsOnTheMove = transform.position == lastPos;
    stick.SetActive(!bIsOnTheMove);
    
  • 另外,我很怀疑您是否希望棍子具有与滚球相同的旋转!当然这会很尴尬

    您肯定不是只是想复制球的方向。我会例如尝试确定 table 边缘到当前球位置的最近点(遍历墙壁碰撞器并使用 Collider.ClosestPoint)并让棍子面向从该边缘点到球位置的方向(+可能是 X 方向的偏移,所以默认情况下摇杆略微倾斜。

  • 最后,您无论如何都不想在每一帧都指定该旋转,因为您以后很可能希望您的用户能够旋转该摇杆。您只想在球静止时应用此一次

例如

// The stick is not a prefab anymore but simply always exists in the scene!
[SerializeField] private Transform stick;
[SerializeField] private Vector3 eulerOffset;
[SerializeField] private Collider[] wallColliders;

public bool bIsOnTheMove;

private Vector3 lastPos;

private void Start()
{
    lastPos = transform.position;
}

private void Update()
{
    // is the ball currently moving?
    var isMoving = transform.position == lastPos;
    last Post = transform.position;

    // Did this state change since the last frame?
    if(bIsOnTheMove == isMoving) return;
    bIsOnTheMove = isMoving;

    // (de)activate the stick accordingly
    stick.gameObject.SetActive(!isMoving);
    
    // Do this ONCE when ball becomes stanionary    
    if(!isMoving)
    {
        var ballPosition = transform.position;

        // among the wall colliders find which one is closest to the ball
        Vector3 closestPoint;
        var smallestDistance = float.PositiveInifinity;
        foreach(var wall in wallColliders)
        {
            var edgePoint = wall.ClosestPoint(ballPosition);
            var distane = (edgePoint - ballPosition).sqrMagnitude;
            if(distance < smallestDistance)
            {
                closestPoint = point;
                smallestDistance = distance;
            }
        }

        // then make the stick look towards the ball from that edge
        var direction = ballPosition - closestPoint;
        var rotation = Quaternion.LookRotation(direction);
        // optional add the offset
        rotation *= Quaternion.Euler(eulerOffset);
 
        stick.rotation = rotation;    
    }
}