这个项目在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 命令将预制组件设置为精灵。
附言如果你有任何关于更好的编码实践的小技巧,也可以随时提出来,努力提高我的编程技能:)
如果 SnakeBody 游戏对象是 SnakeHead 游戏对象的子对象,那么您应该能够在 SnakeBodySprites 脚本中使用
transform.parent.GetComponent<Snake>();
。然而,你已经 GetComponentInParent()
评论了,这让我怀疑你试过这个但 SnakeBody 实际上不是 SnakeHead 的孩子,而是一个单独的,独立的游戏对象。如果您在编辑器中查看对象列表,您应该会看到嵌套在 SnakeHead 对象下的 SnakeBody 对象,以验证它确实是 SnakeHead 的子对象。或者,如果您忘记指定 GetComponentInParent()
的类型,您可以尝试 GetComponentInParent<Snake>();
。希望有所帮助!