我制作了一个简单的消息框,它应该向用户显示一条消息。这是一个预制件并做了几件事,主要是动画在实例化时。为了在实例化时运行代码,我使用了Start()
函数。
当我已经知道要发送消息但我需要constructor
之类的内容时,它会在Start()
之前运行,但在instantiation
之后可以使用参数。
现在,我完全知道我可以实例化,设置消息并运行所有内容 - 所以使用3行代码我实例化它,但我很好奇是否有另一个更合适的解决方案?我在网上找到的只是实例化,然后做点什么。
修改
我打电话给消息框显示:
var timeBox =
Instantiate(messageBox, penaltySpawnLoc.position, penaltyPrefab.transform.rotation, transform);
var scr = timeBox.GetComponent<MessageBox>();
scr.OnCreated(message);
OnCreated
进行初始化,显示动画,基本上都是如此。
但它需要一个string
输入来知道要显示什么,我不想“动态”设置文本值 - 当消息框出现时会出现一些奇怪的闪烁是可见的但文本未设置。
EDIT2:
transform
中的最后一个参数Instantiation
是此脚本所在的Canvas
,因为这是一个UI脚本。该参数意味着新近实例化的GameObject
是其中的孩子。
EDIT3:
timeBox只是messageBox
的一个实例,它们是GameObject
个。
一个消息框仅使用一次。其目的是显示消息,然后在0.5秒后淡出并移开。离开后它会摧毁自己。
答案 0 :(得分:4)
您可以使用函数或扩展方法执行此操作。
在这种情况下,扩展方法更合适。
我们将使用Object
而不是GameObject
制作扩展程序对象。由于GameObject继承自Object,因此该扩展方法应该适用于Object,GameObject和Transform。
创建一个名为ExtensionMethod
的类,然后将其中的所有内容粘贴到其中。
using UnityEngine;
public static class ExtensionMethod
{
public static Object Instantiate(this Object thisObj, Object original, Vector3 position, Quaternion rotation, Transform parent, string message)
{
GameObject timeBox = Object.Instantiate(original, position, rotation, parent) as GameObject;
MessageBox scr = timeBox.GetComponent<MessageBox>();
scr.OnCreated(message);
return timeBox;
}
}
<强>用法强>:
Start
函数中只有一个行调用应该处理所有其他任务。
public class Test: MonoBehaviour
{
GameObject messageBox = null;
Transform penaltySpawnLoc = null;
GameObject penaltyPrefab = null;
void Start()
{
gameObject.Instantiate(messageBox, penaltySpawnLoc.position, penaltyPrefab.transform.rotation, transform, "Hello");
}
}
答案 1 :(得分:1)
我在消息框中使用Factory,所以像
var timebox = MessageBoxFactory.Create(message);
timebox.Show();
并在工厂类中进行设置并返回消息框
public static MessageBox Create(string message) {
var newTimeBox = Instantiate(messageBox, penaltySpawnLoc.position, penaltyPrefab.transform.rotation, transform);
var scr = newTimeBox.GetComponent<MessageBox>();
scr.SetMessage(message);
return scr;
其中Show()是新的OnCreated()。我发现这种模式有助于减少调用代码,如果我需要调整我想要的东西如何被创建,它就在一个地方,共享工厂代码。
答案 2 :(得分:1)
今天遇到了这个问题,并提出了解决方案。这个想法是用自定义方法替换Start()
方法,并实现一个包装器,该包装器将您的预制件及其脚本的构造函数用作其(包装器)构造函数的参数,然后使该包装器实例化并调用您的构造函数。您可以对其进行修改,以支持unity提供的更多重载,但现在对我来说还可以。
EditableGO.cs
:
public class EditableGO<T>
{
GameObject toInstantiate;
Action<T> constructor;
public EditableGO(Action<T> constructor, GameObject toInstantiate = null)
{
this.constructor = constructor;
this.toInstantiate = toInstantiate == null? new GameObject() : toInstantiate;
}
public GameObject Instantiate(Vector3 position, Quaternion rotation, Transform parent = null)
{
GameObject instance;
if(parent != null)
instance = GameObject.Instantiate(toInstantiate, position, rotation, parent);
else
instance = GameObject.Instantiate(toInstantiate, position, rotation);
constructor(instance.GetComponent<T>());
return instance;
}
}
要将Action<T> constructor
传递给EditableGO
的构造函数,我要做的是实现一个静态构造函数生成器。这是一个简单的可定制粒子的示例,请注意构造函数生成器:
public class SimpleParticle : MonoBehaviour
{
public float Duration, Distance, Speed, traveledDistance, birth;
public Vector3 Direction, Size;
public static Action<SimpleParticle> ConstructorGenerator(float duration, float distance, Vector3 size, float speed, Vector3 direction)
{
return (self) => {
self.Duration = duration;
self.Distance = distance;
self.Size = size;
self.Direction = direction;
self.Speed = speed;
self.Init();
};
}
void Init()
{
birth = Time.time;
transform.localScale = Size;
}
void Update()
{
float deltaDist = Speed * Time.deltaTime;
traveledDistance += deltaDist;
transform.position += Direction * deltaDist;
if(Time.time - birth > Duration)
Destroy(this.gameObject);
}
}
然后,实例化新的自定义粒子就像
EditableGO<SimpleParticle> particle = new EditableGO<SimpleParticle>(SimpleParticle.ConstructorGenerator(duration, distance, size, speed, direction), Game.Resources.SimpleParticle);
particle.Instantiate(position, rotation);