在您提供的代码中,除了Start,您没有再设置球的材质颜色。如果你想让球后面的粒子留下不同的颜色,你需要实例化一个新的材质实例。这是因为 Unity 中的材质默认在该特定材质的所有实例之间共享。
所有这些信息以及更多信息都可以在 Material 文档页面上找到。
由于您使用的颜色大小是固定的,因此我将改为创建 6 种新材料并制作一组材料。现在,与其随机选择颜色,不如选择一种材料并将其分配给球或您的新实例绘画能力。我也很困惑为什么你将你的颜色数组放在你的 Start 函数中。只有这样,它才会被本地化为该功能。您似乎还有两个 Start 函数,这很奇怪。一个是 Monobehaviour Start,另一个是 start。除非有意,否则您的第二个 start 将不会运行,除非您调用它。
现在开始讨论我所说的解决方案。
// assign these in the inspector to your new materials
[SerializeField] private List<Material> materials = new List<Material>();
private MeshRenderer meshRender;
private void Start()
{
meshRenderer = GetComponent<MeshRenderer>();
// set our first random Material
SetNewMaterialColor();
}
private void SetNewMaterialColor()
{
meshRenderer.material = GrabNewMaterial();
}
private void FixedUpdate()
{
// Set the balls speed when it should travel
if (isTraveling) {
rb.velocity = travelDirection * speed;
}
// Paint the ground
Collider[] hitColliders = Physics.OverlapSphere(transform.position - (Vector3.up/2), .05f);
int i = 0;
while (i < hitColliders.Length)
{
GroundPiece ground = hitColliders[i].transform.GetComponent<GroundPiece>();
if (ground && !ground.isColored)
{
// change this from a color to a material instead
ground.Colored(meshRenderer.material);
// set a new material to your main object
SetNewMaterialColor();
}
}
}
private Material GrabNewMaterial()
{
return materials[UnityEngine.Random.Range(0, materials.Count)];
}
您需要更改Colored 函数以接收Material 而不是Color。如果您希望实现更加动态,您可以改为创建材质实例并动态设置颜色,但由于您有固定大小的颜色,我认为您不需要这样做。
编辑:另一个涉及创建新着色器的选项是使用[PerRendererData],这意味着属性字段的每个对象都是单独渲染的。我会选择上一个选项,因为使用着色器或实例化材质的任何一个选项都比较复杂。
您需要使用MaterialPropertyBlock,然后可以在需要时指定颜色。它看起来像
public void SetNewColor()
{
// create a new material property block
MaterialPropertyBlock tmpBlock = new MaterialPropertyBlock();
// grab the current block from our renderer
meshRender.GetPropertyBlock(tmpBlock);
// set our changes to the block
tmpBlock.SetColor("_Color", YourColorHere);
// now apply our changes
tmpRend.SetPropertyBlock(tmpBlock);
}
您需要使用PerRendererData 属性创建一个新的着色器,该着色器在Main Color 属性之后。
Properties
{
[PerRendererData]_Color("Main Color", Color) = (1,1,1,1)
...
另外,我还有一个问题是为什么你使用Physics.OverlapSphere 而不仅仅是OnCollisionEnter?或者如果你的游戏是 2D 的,那么 OnCollisionEnter2D 并让物理引擎处理碰撞的工作方式,然后在发生碰撞时更改颜色?
编辑:以下是您问题的答案 - 如果您有更多问题,请告诉我。
在“[SerializeField] private List materials = new
List();" 我需要将哪个部分替换为
材料和方法?
这条线很好。通过使用[SerializeField],它将这个列表暴露给编辑器。您将需要创建几个使用 6 种不同颜色的新重复材料。您现在将设置材料,而不是设置颜色。我所说的检查器和编辑器的意思是您可以在 Unity 中找到带有此脚本的对象,选择它(它必须是预制件或在场景中),然后 Unity 编辑器的选项卡将填充有关此对象的信息.找到脚本部分并找到字段materials。应该有一个下拉箭头,单击它并将数字设置为6(或任何您想要的材料交换)。现在用您的颜色创建 6 种新材料并将它们拖到出现的框中。
会不会类似于在 () 中写“./Materials/Ball 1”
例子?
不!您将在检查器中分配此数据,因此数据将存储在列表中,而无需在代码中引用它们。
我不确定如何使用“[SerializeField] 将其分配给我的球
私有游戏对象paintObject = null;"
同样,这会出现在检查器中。但是,请删除此行,因为我误解了您的原始问题并不小心将其留在了其中。我认为您的绘画对象是您在球反弹后生成的预制件,而不是您要更改颜色的地面。
我收到错误“参数 1:无法从
'UnityEngine.Material' 到 'UnityEngine.Color'"
是的!因此,正如我在 cmets 中提到的,您对绘制对象的函数调用目前很可能采用 Color 参数。当我将您的实现更改为直接设置Material 时,您将需要更改该函数签名的方式。具体如下:
ground.Colored(meshRenderer.material);
您有一些对象ground,它的类型为GroundPiece,并且有一个名为Colored 的函数。我认为它目前看起来像:
public void Colored(Color color){...}
您想改为:
public void Colored(Material mat{...}
更改后,您无需在此脚本中更改地面颜色,而是直接更改其材质。如果您还有其他问题,请告诉我。