首页 > 解决方案 > 玩家重生后石头没有在正确的地方产卵

问题描述

当玩家重生时,我希望石头(可以由玩家移动)回到原来的位置。这对我不起作用。相反,石头会在附近的其他位置生成,有时会在地图外生成。所有石头都被标记为石头。

我已经尝试反转向量并反转减法等的符号。

这是播放器脚本。

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

    public class PlayerControll : MonoBehaviour
    {
        public bool isTouchingGround = false;

        public GameObject locater1;

        public GameObject locater2;

        public GameObject currentCheckPoint;

        public GameObject playerPrefab;

        public Rigidbody2D myRigidBody;

        public GameObject GameMaster;
        // Start is called before the first frame update
        void Start()
        {

            isTouchingGround = false;
           GameObject MyGameMaster= Instantiate(GameMaster, new Vector3(0, 0, 0), Quaternion.identity);
            GameMaster = MyGameMaster;
        }

        // Update is called once per frame
        void Update()
        {
            if (Input.GetKey("a"))
            {
                transform.Translate(-0.1f, 0, 0);

            }


            if (Input.GetKey("d"))
            {
                transform.Translate(0.1f, 0, 0);
            }

            if ((Input.GetKey("w") || Input.GetKey("space")) && isTouchingGround == true)
            {
                myRigidBody.AddForce(new Vector2(0f, 130f));
            }

            if (locater1.transform.position.y <= locater2.transform.position.y)
            {
                ReSpawn();

            }
        }

        private void OnCollisionEnter2D(Collision2D collision)
        {
            if (collision.gameObject.tag == "Platform" || collision.gameObject.tag == "Stone")
            {
                isTouchingGround = true;
            }
        }

        private void OnCollisionExit2D(Collision2D collision)
        {
            if ((collision.gameObject.tag == "Platform" || collision.gameObject.tag == "Stone") && locater2.transform.position.y > collision.transform.position.y) 
            {
                isTouchingGround = false;
            }

        }


        private void OnTriggerEnter2D(Collider2D collision)
        {
            if (collision.gameObject.tag == "CheckPoint")
            {
                currentCheckPoint = collision.gameObject;
            }


            if (collision.gameObject.tag == "Radiation")
            {
                ReSpawn();
            }
        }

        public void ReSpawn()
        {
            GameMaster.gameObject.GetComponent<ReverToOriginalPositions>().RevertToOrignalPosition();
            GameObject currentPlayer=Instantiate(playerPrefab, currentCheckPoint.transform.position, currentCheckPoint.transform.rotation);
            currentPlayer.GetComponent<PlayerControll>().isTouchingGround = false;

            Destroy(this.gameObject);







        }


    }

这是 RememberPositions 脚本。这属于每一块石头都要记住在开始时的位置。

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

public class RememberPositions : MonoBehaviour
{

    public float StartXPosition;
    public float StartYPosition;

    float StartRotation;
    // Start is called before the first frame update
    void Start()
    {
        StartXPosition = transform.position.x;
        StartYPosition = transform.position.y;
        StartRotation = transform.rotation.z;
    }

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

    }
}

这是 RevertToOriginalPosition 脚本。这会将石头恢复到原来的位置。这是在 GameMaster/MasterControll 中。

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

public class ReverToOriginalPositions : MonoBehaviour
{

    public GameObject[] allStones;


    // Start is called before the first frame update
    void Start()
    {
        allStones = GameObject.FindGameObjectsWithTag("Stone");



    }

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

    }

    public void RevertToOrignalPosition()
    {
        for (int i = 0; i < allStones.Length; i++)
        {
            allStones[i].gameObject.transform.Translate((new Vector3((allStones[i].gameObject.GetComponent<Transform>().position.x- allStones[i].gameObject.GetComponent<RememberPositions>().StartXPosition) , (allStones[i].gameObject.GetComponent<Transform>().position.y- allStones[i].gameObject.GetComponent<RememberPositions>().StartYPosition), 0)));
            allStones[i].gameObject.transform.Rotate(0, 0, -allStones[i].gameObject.transform.rotation.z);
        }




    }
}

这是商店接收者脚本。这是针对另一种称为 Activator 的游戏机制。这不是那么重要,但我还是把它包括在内。

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

public class StoreReciever : MonoBehaviour
{

    public GameObject reciever;
    // Start is called before the first frame update
    void Start()
    {

    }

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

    }

   void OnTriggerEnter2D(Collider2D collision)
    {
        reciever.gameObject.GetComponent<PolygonCollider2D>().enabled = true;
    }

     void OnTriggerExit2D(Collider2D collision)
    {
        reciever.gameObject.GetComponent<PolygonCollider2D>().enabled = false;
    }
}

根本没有错误消息。只是石头在他们不应该的地方重生。感谢您的帮助。

标签: c#unity3d

解决方案


只需制作一些字段/属性,它们甚至不必是私有静态只读

public static readonly Vector3 StartPos = new Vector3(1.0f, 2.0f, 3.0f);
public static readonly Vector3 StartRot_In_EulerAngles = new Vector3(1.0f, 2.0f, 3.0f);

然后你可以在一个方法中做这样的事情:

public static void ResetMyStones()
{
   var allStones = GameObject.FindGameObjectsWithTag("Stone");
   foreach(var stone in allStones)
   {
      stone.transform.position = StartPos;
      stone.transform.eulerAngles = StartRot_In_EulerAngles;
   }
}

关于欧拉角:

为什么是欧拉角?- 因为 Unity 使用所谓的四元数进行旋转,所以不会发生Gimbal 锁定,但不好的是,如果您不深入了解四元数,您无法真正单独设置 xyz 组件,但是如果您只想设置并获得当前的旋转欧拉角度是完美的,因为您可以使用传统的 x,y,z 组件来设置值。

补充说明:

你的代码有点长而且结构不好,就像ReverToOriginalPositions应该是一个方法而不是一个组件,也不是所有的东西都必须是从单一行为派生的。

还要删除未使用的Update方法,如果它在脚本中但未使用它们会产生很小的开销(通常它无法衡量,但在更大的项目中它会影响性能:)),也许如果你的游戏是这样构建的,你可以存储所有当前GameManager 类列表中的石头,因此您无需调用GameObject.FindGameObjectsWithTag("Stone");


推荐阅读