从预制脚本中的父脚本检索变量 [C#]

问题描述 投票:0回答:1

这个项目在Unity中,是2D的,是一个基本的多人贪吃蛇游戏。我目前正在尝试解决蛇身体部分的方向朝向正确方向的问题。

我有两个脚本,Snake.cs 和 SnakeBodySprites.cs

在包含脚本 Snake.cs 的游戏对象“SnakeHead”中,有一个名为“SnakeBody”的预制件,其中包含一个脚本“SnakeBodySprites”。我的目标是检索在 Snake.cs 脚本中声明的段变换列表,以便我可以在我的 SnakeBodySprites 脚本中使用它来比较前后的变换是否在特定的 X 和 Y 坐标处。根据结果给那个预制件一个特定的精灵。

snakebodysprites.cs 脚本:

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

public class SnakeBodySprites : MonoBehaviour
{
    [SerializeField] private Snake SnakeScript;

    //sprites for snake body
    public Sprite SnakeBodyHorizontal;
    public Sprite SnakeBodyVertical;
    public Sprite SnakeBodyCornerLeftDown;
    public Sprite SnakeBodyCornerRightDown;
    public Sprite SnakeBodyCornerLeftUp;
    public Sprite SnakeBodyCornerRightUp;

    private int orientation = 7;

    //Snake myScript = SnakeBodySprites.GetComponentInParent<Snake>();
    //myScript.myVariable = whatever // set variable
    //myScript.myFucntion() // runs function 

    //GameObject.GetComponentInParent


    //If there is an object to the left and to the right, if yes, you're a horizontal piece
    //If there is a piece above and below you, you are a vertical piece
    //If there is a piece above and to the left, you're a corner piece
    //if there is a piece above and to the right, you're a corner piece
    //if there is a piece below and to the right, you're a corner piece
    //if there is a piece below and to the left, you're a corner piece

    // Update is called once per frame
    void Update()
    {
        //Debug.Log();

        if (orientation == 1){
            Debug.Log("horizontal");
        } else if (orientation == 2){
            Debug.Log("vertical");
        }
        else if (orientation == 3){
            Debug.Log("CornerLeftDown");
        }
        else if (orientation == 4){
            Debug.Log("CornerRightDown");
        }
        else if (orientation == 5){
            Debug.Log("CornerLeftUp");
        }
        else if (orientation == 6){
            Debug.Log("CornerRightUp");
        }
    }
}

snake.cs 脚本:

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

public class Snake : MonoBehaviour
{

    private Vector2 _direction = Vector2.right;
    private KeyCode lastHitKey = KeyCode.D;

    public Transform segmentPrefab;
    public int initialSize = 3;
    public Sprite SnakeHeadUp;
    public Sprite SnakeHeadRight;
    public Sprite SnakeHeadLeft;
    public Sprite SnakeHeadDown;
    public List<Transform> _segments = new List<Transform>();

    private void Start()
    {
        ResetState();
    }


    // Update: Updated Once Per Time (Edit -> Project Settings -> Time (0.09) to change difficulty!)
    // This function is controlling the direction our snake moves.
    void Update()
    {

        if (Input.GetKeyDown(KeyCode.W) && lastHitKey != KeyCode.S) {
            this.gameObject.GetComponent<SpriteRenderer>().sprite = SnakeHeadUp;
            lastHitKey = KeyCode.W;
            _direction = Vector2.up;
        } 
        
        else if (Input.GetKeyDown(KeyCode.S) && lastHitKey != KeyCode.W){
            this.gameObject.GetComponent<SpriteRenderer>().sprite = SnakeHeadDown;
            lastHitKey = KeyCode.S;
            _direction = Vector2.down;
        } 
        
        else if (Input.GetKeyDown(KeyCode.A) && lastHitKey != KeyCode.D) {
            this.gameObject.GetComponent<SpriteRenderer>().sprite = SnakeHeadLeft;
            lastHitKey = KeyCode.A;
            _direction = Vector2.left;
        } 
        
        else if(Input.GetKeyDown(KeyCode.D) && lastHitKey != KeyCode.A)
        {
            this.gameObject.GetComponent<SpriteRenderer>().sprite = SnakeHeadRight;
            lastHitKey = KeyCode.D;
            _direction = Vector2.right;
        }
    }

    //This transforms the position of our snake head, rounded to a whole number. This should force our snake to move in a grid.
    public void FixedUpdate()
    {

        for (int i = _segments.Count - 1; i > 0; i--){
            _segments[i].position = _segments[i - 1].position;
        }


        this.transform.position = new Vector3(
            Mathf.Round(this.transform.position.x) + _direction.x,
            Mathf.Round(this.transform.position.y) + _direction.y,
            0.0f
        );

    }

    //Function handles the logic of iterating in reverse from a list of prefabs of our snake segments, to create a new snake segment.
    private void Grow()
    {
        Transform segment = Instantiate(this.segmentPrefab);
        segment.position = _segments[_segments.Count - 1].position; //each segment inherits position

        _segments.Add(segment);
    }

    //Function handles the logic of resetting the state of our game upon collision with objects other than food
    private void ResetState(){

        //emptying the snakelist
        for(int i = 1; i < _segments.Count; i++)
        {
            Destroy(_segments[i].gameObject);
        }

        _segments.Clear();
        _segments.Add(this.transform);

        //resetting our snake from 1 back to initialsize (3)
        for(int i = 1; i < this.initialSize; i++)
        {
            _segments.Add(Instantiate(this.segmentPrefab));
            //initalizing the original segments
            _segments[i].position = new Vector3(
            -50.0f,
            0.0f,
            0.0f
        );
        }

        this.transform.position = new Vector3(
            -5.0f,
            0.0f,
            0.0f
        );
    }

    private void OnTriggerEnter2D(Collider2D other) {
            if (other.tag == "Food") {
                Grow();
            } else if (other.tag == "Obstacle") {
                ResetState();
        }
    }
}

我在这个解决方案上工作了一段时间,你可以在 snakebodysprites.cs 脚本中看到很多调试/测试注释。 Private int 方向只是我测试方向,我打算将其更改为不同的值,并在我能够检索必要信息时让 if 命令将预制组件设置为精灵。

附言如果你有任何关于更好的编码实践的小技巧,也可以随时提出来,努力提高我的编程技能:)

c# unity3d
1个回答
0
投票

如果 SnakeBody 游戏对象是 SnakeHead 游戏对象的子对象,那么您应该能够在 SnakeBodySprites 脚本中使用

transform.parent.GetComponent<Snake>();
。然而,你已经
GetComponentInParent()
评论了,这让我怀疑你试过这个但 SnakeBody 实际上不是 SnakeHead 的孩子,而是一个单独的,独立的游戏对象。如果您在编辑器中查看对象列表,您应该会看到嵌套在 SnakeHead 对象下的 SnakeBody 对象,以验证它确实是 SnakeHead 的子对象。或者,如果您忘记指定
GetComponentInParent()
的类型,您可以尝试
GetComponentInParent<Snake>();
。希望有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.