Unity,改变子对象的旋转。无法访问子对象

Unity, Changing the rotation of a child object. Cannot access the child object

我正在设计 2D 游戏中玩家瞄准和射击的逻辑。当用户在屏幕上单击并拖动时,它应该围绕精灵旋转一条由 3 个点组成的线,其角度与玩家拖动的角度相同,以便他可以瞄准。就像泡泡射手一样。

"Player" 预制件有一个名为 "Sight" 的子对象,它是一个以 4 个点精灵作为子对象及其相应偏移量的变换,因此旋转 "Sight" 将旋转整条线.

在我查看的每个更新循环中,瞄准器根据鼠标位置旋转它,但变量瞄准器似乎为空。我试图通过标签获取对象,并有一个 public 变量,这样我就可以从检查员那里分配预制件。我也试图只抓取转换组件。我敢肯定这是一个非常愚蠢的问题,但我看不到。如果有任何帮助,我将不胜感激。

瞄准逻辑:

public class PlayerShooting : MonoBehaviour {

    public GameObject BulletPrefab;
    public float coolDownTimer = 0.0f;
    public float aimDistance = 0.5f;

    private Vector2 originPoint = new Vector2 (0f,0f);
    private Vector2 endPoint = new Vector2(0f,0f);

    private bool dragging = false;
    public GameObject sight;

    // Update is called once per frame
    void Update () {

        // TOUCH DOWN
        if (Input.GetMouseButtonDown(0) == true) {
            originPoint = getPointInWorld(Input.mousePosition);
            endPoint = originPoint;
            dragging = true;
        }

        // TOUCH UP
        if (Input.GetMouseButtonUp(0) == true) {
            endPoint = getPointInWorld(Input.mousePosition);
            dragging = false;
            FireBullet();
        }

        // DRAGGING
        if (dragging) {


            endPoint = getPointInWorld(Input.mousePosition);
            // AIM
            // !!!: THIS IS THE ISSUE
            sight = GameObject.Find("Player/Sight");
            if (sight != null && endPoint != originPoint) {
                Vector2 dir = originPoint - endPoint;
                dir.Normalize();    
                float zAngle = Mathf.Atan2 (dir.y,dir.x) * Mathf.Rad2Deg - 90;
                Quaternion newRotation = Quaternion.Euler(0,0,zAngle);
                sight.transform.rotation = newRotation;
            }
            else
            {
                Debug.Log("Error: cannot aim because Sight was not instantiated");
            }
        }
    }

    void FireBullet (){

    }

    Vector2 getPointInWorld (Vector3 point){
        Vector2 pos = Camera.main.ScreenToWorldPoint(point);
        return pos;
    }
}

好的,您的脚本中有多个不推荐的做法。正如您所说,您应该更喜欢 FindObjectWithTag,更好的是,通过检查器分配它。为此,请执行以下操作:创建一个名为 sightReference 的 public 变量(或具有 [Serializable] 属性的私有变量)。然后保存你的脚本。将其附加到播放器后,将 "Sight" 拖到检查器脚本中的 sightReference(选择播放器对象后,如果展开脚本,您应该会看到一个空字段);目前,它在您发布的图片中显示 None(游戏对象),将视线拖到那里。

另外,为了检测拖动,你应该使用事件,而不是通过输入来推断。如果你想要一个关于事件的精彩教程,watch this one(你可以从头开始观看,但你需要的是从那个时候开始)。要么实现接口(我会推荐,即使一开始看起来很难很容易),要么统一使用事件触发组件。

旧答案:

好的,假设您希望直线始终为 3 个点。我会做的是创建一个 3 点的精灵。这样,它只是一个对象(您可以使用 3 个单独的精灵来完成,但它可能会变得更复杂,所以为了简单起见,我将采用这个假设 - 您可以稍后更改它)。

确保瞄准线精灵的轴心点在精灵的底部中间(你可以在线查找,设置轴心在精灵编辑器中)。您也可以将它留在中间,并创建一个位于底部中间的父对象,并将其用作枢轴,但同样,现在要简单。

现在您有了一个带有该精灵的对象,它围绕其轴心点旋转,该轴心点位于其底部中间,因此它像时钟指针一样工作。尝试在检查器中更改旋转以验证这一点。

现在,让这条瞄准线的父级成为玩家,这样它就会跟随玩家。调整它的位置,使其不与播放器重叠。

现在,编写脚本并将其附加到瞄准线上。在 C# 中:

void Update()
{
    Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    Vector3 lineWorldPosition = this.transform.parent.position;
    Vector3 lookAtVector = mouseWorldPosition - lineWorldPosition;
    float angle = Mathf.Atan2(lookAtVector.x, lookAtVector.y) * Mathf.Rad2Deg;
    this.transform.localRotation = Quaternion.Euler(0, 0, -angle);
}

这假设旋转 0,0,0 时瞄准线与 Y 轴对齐(它指向上方)。

退一步看,似乎没有对象可以分配给变量 sight,因为场景文件已损坏。它是从 Bitbucket 存储库克隆而来的。原来的方法工作正常,指令

sight = GameObject.Find("Player/Sight");

能够找到对象。我决定从脚本而不是编辑器中分配它,这样我就可以在玩家是否射击时启用和禁用瞄准器。