我正在创建一个小型2D游戏,您需要在其中生存。每棵树都有其自己的强度=5。当玩家碰撞并按下鼠标左键时,强度为-1,玩家木材状态为+1。当树的强度等于或小于0时,树将被破坏。这是我的代码:(问题在代码后面)
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Stats: MonoBehaviour
{
//Player Stats
public float hp = 100;
public float wood = 0;
//Tree stats
public float treeLogStrenth = 5;
//Text
public Text woodText;
void Start ()
{
woodText.text = "0";
}
void Update ()
{
woodText.text = wood.ToString();
if (treeLogStrenth <= 0)
{
Destroy(GetComponent<PlayerCollisions>().;
}
}
}
这是另一个代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCollisions: MonoBehaviour
{
public void OnCollisionStay2D (Collision2D collisionInfo)
{
if (collisionInfo.gameObject.tag == "Tree" && Input.GetMouseButtonDown(0))
{
string treeName = collisionInfo.gameObject.name;
GetComponent<Stats>().wood += 1;
GetComponent<Stats>().treeLogStrenth -= 1;
}
}
}
我的问题:如何像制作一个简单的代码一样,而不是一直为每棵树都创建另一个游戏对象并销毁它,而不是一直这样做。请帮助(最新版本)
答案 0 :(得分:0)
所以要清理一下:Stats
应该附加在播放器上,对吗?
您不应该在Update
的每一帧中都做事,而应该像事件驱动一样
public class Stats : MonoBehaviour
{
// You should never allow your stats to be set via public fields
[SerializeField] private float hp = 100;
[SerializeField] private float wood = 0;
// if you need to read them from somewhere else you can use read-only properties
public float HP => hp;
public float Wood => wood;
[SerializeField] private Text woodText;
private void Start ()
{
woodText.text = "0";
}
public void AddWood(int amount)
{
wood += amount;
woodText.text = wood.ToString();
}
}
然后,每棵树都应该附加自己的组件实例,例如
public class Tree : MonoBehaviour
{
[SerializeField] private float treeLogStrenth = 5;
public void HandleClick(Stats playerStats)
{
// if this tree has wood left add it to the player stats
if(treeLogStrength > 0)
{
playerStats.AddWood(1);
treeLogStrenth -= 1;
}
// destroy this tree when no wood left
if (treeLogStrenth <= 0)
{
Destroy(gameObject);
}
}
}
,最后也连接到播放器
public class PlayerCollisions: MonoBehaviour
{
// better already reference this via the Inspector
[SerializeField] private Stats stats;
// will store the currently collided tree in order to reuse it
private Tree currentlyCollidedTree;
// as fallback initialize it on runtime
private void Awake()
{
if(!stats) stats = GetComponent<Stats>();
}
private void OnCollisionStay2D(Collision2D collisionInfo)
{
if (collisionInfo.gameObject.CompareTag("Tree") && Input.GetMouseButtonDown(0))
{
// Get the Tree component of the tree object you are currently colliding with
// but only once and store the reference in order to reuse it
if(!currentlyCollidedTree) currentlyCollidedTree= collisionInfo.gameObject.GetComponent<Tree>();
// tell the tree to handle a click and pass in your stats reference
currentlyCollidedTree.HandleClick(stats);
}
}
// reset the currentlyCollidedTree field when not colliding anymore
private void OnCollisionExit2D()
{
currentlyCollidedTree = null;
}
}
是的,有一种替代方法,不是每棵树都需要自己的组件实例,但我建议不要实际使用它!
您可以让玩家记住他已经点击过的那棵树
public class PlayerCollisions: MonoBehaviour
{
// better already reference this via the Inspector
[SerializeField] private Stats stats;
// will store all trees we ever clicked on in relation to the according available wood
private Dictionary<GameObject, int> encounteredTrees = new Dictionary<GameObject, int>();
// as fallback initialize it on runtime
private void Awake()
{
if(!stats) stats = GetComponent<Stats>();
}
private void OnCollisionStay2D(Collision2D collisionInfo)
{
if (collisionInfo.gameObject.CompareTag("Tree") && Input.GetMouseButtonDown(0))
{
// did we work on this tree before?
if(encounteredTrees.Contains(collisionInfo.gameObject))
{
// if so gain one wood and remove one from this tree
stats.AddWood(1);
encounteredTrees[collisionInfo.gameObject] -= 1;
// destroy the tree if no wood available and remove it from the dictionary
if(encounteredTrees[collisionInfo.gameObject] <= 0)
{
encounteredTrees.RemoveKey(collisionInfo.gameObject);
Destroy(collisionInfo.gameObject);
}
}
else
{
// the first time we work this tree gain one wood and add
// the tree as new entry to the dictionary with 4 wood left
stats.AddWood(1);
encounteredTrees.Add(collisionInfo.gameObject, 4);
}
}
}
}
但是,这极大地限制了您,并且您再也无法拥有不同的树木预制件具有不同数量的可用木材...