我有一个太空射击游戏,玩家可以为飞船选择一种颜色,这也适用于飞船射击的子弹。这些飞船使用相同的子弹预制件,因此我想在游戏中创建子弹后更改其颜色。我最初使用以下代码更改颜色。
Material bulletMat = this.GetComponent<MeshRenderer>().sharedMaterial;
if (bulletMat != null)
{
bulletMat.SetColor("_TintColor", color);
}
但是,我发现这会改变材料的颜色,并且在创建每个项目符号时,项目符号会在颜色之间切换。经过更多研究之后,我遇到了 MaterialPropertyBlock 变量和以下教程http://thomasmountainborn.com/2016/05/25/materialpropertyblocks/。因此,我遵循了本教程并设置了以下代码。
public Renderer renderer;
public MaterialPropertyBlock matBlock;
public Color color;
public bool colorSet = false;
void Awake()
{
renderer = this.GetComponent<Renderer>();
matBlock = new MaterialPropertyBlock();
}
public void ColorSet(Color color)
{
this.color = color;
this.colorSet = true;
}
void Update()
{
if (this.colorSet)
{
renderer.GetPropertyBlock(matBlock);
matBlock.SetColor("_Color", this.color);
renderer.SetPropertyBlock(matBlock);
}
}
但是,发生了与先前解决方案相同的问题。...
有人可以帮我弄清楚如何为每个子弹设置颜色吗?
答案 0 :(得分:2)
仅在真正要使用此材料更改每个对象的材料的地方使用sharedMaterial
。那就是你不想做的。相反,您必须使用material
,因此您只需更改材料的“克隆”实例。
如果这样做,Unity实际上只会自动为该对象实例化当前材料的本地副本。
public class ColorChanger : MonoBehavior
{
private MeshRenderer meshRenderer;
private void OnEnable()
{
meshRenderer = GetComponent<MeshRenderer>();
}
public void SetColor(Color newColor)
{
renderer.material.color = newColor;
}
}
或使用SetColor
,就像我猜得到的一样
public void SetColor(Color newColor)
{
renderer.material.SetColor("_TintColor", newColor);
}
我个人比较容易找到以前提到的一种。但是第二个可以给你更多的控制权,因为你可以还可以更改其他方式无法实现的emitColor。
现在,当实例化子弹时,请确保首先实例化预制件,然后使用上面的组件更改颜色:
public GameObject bulletPrefab;
public Color myColor;
public GameObject Hand;
private void Shoot()
{
// There are various ways for Instantiate e.g. providing start position and rotation or also the parent object
// Since it shall be fired from the player I'll assume here there is a "Hand" object from which you want to fire
// and that you want to add the bullet directly to the hierarchy without a parrent
GameObject newBullet = Instantiate(bulletPrefab, Hand.position, Hand.rotation);
// Now we get the color change component
ColorChanger colorChanger = newBullet.GetComponent<ColorChanger>();
// And set the color
colorChanger.SetColor(myColor);
}
注意:
如果是多人游戏,则子弹应仅在服务器上实例化,因此您必须首先让服务器知道子弹应为哪种颜色,然后Network.Spawn
后再将此信息提供给所有玩家他们。
答案 1 :(得分:1)
您不需要继续更新属性块。一次就够了。您还必须确保材质允许实例化,并且着色器支持实例化“ _Color
”。在标准材质和精灵材质上,您会在材质的检查器窗口的底部找到它。
因此,您可以在Update
中删除测试,并修改ColorSet
方法。实际上,在Bullet类型的对象上,我倾向于使其尽可能精简(最好将所有功能移至中央Bullet Manager,但这不在主题之列。)
public void ColorSet(Color color)
{
renderer.GetPropertyBlock(matBlock);
matBlock.SetColor("_Color", color);
renderer.SetPropertyBlock(matBlock);
}
如果这没有帮助,您是否正在从已经在对象上设置颜色的水池中抓弹?只是在没有为已实例化的对象设置正确的颜色的情况下?
我也在质疑为什么renderer.material
不起作用(或者您是否尝试过?)。但是,根据我的理解/猜测,设置新材料实际上会破坏实例化。因此,无论如何设置属性块,实际上可能会获得更好的性能。