我正在尝试制作像z-type
这样的堕落文字游戏。游戏开始后,屏幕上会显示几个单词。当用户键入一个字母并且与所显示的任何单词的第一个字母匹配时,会在该单词中添加activeWord
标记。我还创建了一个激光脚本,用于检查标签是否处于活动状态,当发生这种情况时,它会拍摄激光。
现在正在发生的事情是激光仅被拍摄一次,即第一个字母匹配但在输入剩余的单词时不会拍摄激光。
这是激光脚本:
using UnityEngine;
using UnityEngine.UI;
public class Laser : MonoBehaviour {
public float speed = 10.0f;
private Vector3 laserTarget;
private void Update () {
GameObject activeWord = GameObject.FindGameObjectWithTag("activeWord");
if (activeWord && activeWord.GetComponent<Text>().text.Length > 0) {
laserTarget = activeWord.transform.position; // find position of word
transform.Translate(laserTarget * speed * Time.deltaTime); // shoot the laser
}
}
}
我还在显示/ UI字段中添加了我使用的代码。
public void RemoveLetter() {
/* remove the first letter if its correct and so
on for the remaining letters. change the color of the word to red and add
the "activeddWord" tag.*/
text.text = text.text.Remove(0, 1);
text.color = Color.red;
text.gameObject.tag = "activeWord";
}
public void RemoveWord() { // destroy the word once all the letters match
Destroy(gameObject);
}
有人可以查看代码并告诉我我在哪里犯了错误。
答案 0 :(得分:2)
我认为如果激光到达目标,你必须重置激光的位置:
public float speed = 10.0f;
private Vector3 laserTarget;
private Vector3 laserOrigin;
private void Start () {
// save laser's origin position
laserOrigin = transform.position;
}
private void Update () {
GameObject activeWord = GameObject.FindGameObjectWithTag("activeWord");
if (activeWord && activeWord.GetComponent<Text>().text.Length > 0)
{
laserTarget = activeWord.transform.position; // find position of word
transform.Translate(laserTarget * speed * Time.deltaTime); // shoot the laser
float distance = Vector3.Distance(laserTarget , transform.position);
if(distance < 0.05f){ // I don't know your scaling, perhaps change the limit here!
transform.position = laserOrigin;
}
}
}
答案 1 :(得分:1)
以下是使用Instantiate()
和预制件执行此操作的一种方法。这种方法的好处是可扩展。您可以创建多个激光器,只需最少的调整。请注意,要使用多个激光,您必须删除WaitForThisLaserDestroyed;
。
要实现这一点,您必须首先将激光游戏对象更改为预制件并将此脚本添加到其中:
https://docs.unity3d.com/Manual/Prefabs.html
public class Laser : MonoBehaviour
{
public float speed = 10.0f;
public Vector3 laserTarget;
public float destroyLaserAfterTime = 3f;
private void Update ()
{
transform.Translate(laserTarget * speed * Time.deltaTime);
}
}
然后在一些任意的其他对象上。例如,同一场景中的空游戏对象:
public class LaserInitializer : MonoBehaviour
{
public GameObject laserPrefab;
public GameObject laserOrigin;
private GameObject WaitForThisLaserDestroyed;
private void Update ()
{
GameObject activeWord = GameObject.FindGameObjectWithTag("activeWord");
if (WaitForThisLaserDestroyed == null && activeWord && activeWord.GetComponent<Text>().text.Length > 0)
{
CreateLaser(activeWord);
}
}
private void CreateLaser(GameObject activeWord)
{
GameObject activeLaser = Instantiate(laserPrefab, laserOrigin.Transform.Position, Quaternion.identity) as GameObject;
Laser laserScript = activeLaser.GetComponent<Laser>();
laserScript.laserTarget = activeWord.transform.position;
WaitForLaserDestroyed = activeLaser;
Destroy(activeLaser, destroyLaserAfterTime);
}
}
解释代码:
激光预制件有自己的脚本移动到单词,一旦它存在并将目标传递给它,它将移动到活动单词。
在场景中的其他地方,您有一个游戏对象,用于存放第二个脚本。让我们称之为“控制器游戏对象”。它按照早期的设计检查单词是否“活动”。当一个单词处于活动状态时,该脚本只会创建一个激光,并告诉它定位活动单词。
你有另一个游戏对象(这可能与控制器游戏对象相同),它标志着激光的起源。您可以通过其他方式执行此操作,但我认为使用游戏对象标记起点对初学者来说是一种简单的方法。