我正在制作一个小型平台游戏,在那儿,我制作了一个可以更改播放器颜色的场景。我制作了3个按钮,当您单击它们时会更改颜色。我还制作了两个代码文件,但是它们不起作用。我也没有在控制台中看到任何错误。 请注意,换色代码和按钮与游戏对象不在同一场景。
这是更改颜色的按钮的代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColourManager : MonoBehaviour
{
public static int colour;
public void DefaultBlue()
{
colour = 0;
}
public void Green()
{
colour = 1;
}
public void Red()
{
colour = 2;
}
}
这是游戏对象本身的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColourTarget : MonoBehaviour
{
void Start()
{
rend = GetComponent<Renderer>();
rend.sharedMaterial = materials[0];
rend.enabled = true;
}
private Renderer rend;
public int lcolour = ColourManager.colour;
public Material[] materials;
private void Update()
{
if (lcolour == 0)
{
rend.sharedMaterial = materials[0];
}
if (lcolour == 1)
{
rend.sharedMaterial = materials[1];
}
if (lcolour == 2)
{
rend.sharedMaterial = materials[2];
}
}
}
答案 0 :(得分:2)
请注意,更改sharedMaterial
可能不是您要在此处执行的操作。
如果要修改渲染器的材质,请使用材质。
因此,请使用material
。尤其是一次颜色已更改,并且您正在处理实例材质,此后更改共享材质完全无效。
然后不要在Update
中执行此操作!设置每帧!
最后请注意
public int lcolour = ColourManager.colour;
仅在该对象初始化后一次一次被分配,然后不再更改... int
是 VALUE 类型,而不是引用!< / p>
我宁愿使用和event
并让您的目标监听所有更改。
所以您的代码可能看起来像
public class ColourManager : MonoBehaviour
{
public static int colour;
// we will invoke this event everytime the color index is changed
// and directly pass the according new index in
public static event Action<int> OnColourIndexChanged;
public void DefaultBlue()
{
colour = 0;
// The ? is a null check and only
// calls Invoke if there is at least one listener to this event
OnColourIndexChanged?.Invoke(colour);
}
public void Green()
{
colour = 1;
OnColourIndexChanged?.Invoke(colour);
}
public void Red()
{
colour = 2;
OnColourIndexChanged?.Invoke(colour);
}
}
然后
public class ColourTarget : MonoBehaviour
{
[SerializeField] private Renderer _renderer;
public Material[] materials;
private void Awake()
{
if(!_renderer) _renderer = GetComponent<Renderer>();
_renderer.enabled = true;
// Add a callback to the event
// Removing it first is save also if it wasn't added so far
// This just makes sure it is always added only exactly once
ColourManager.OnColourIndexChanged -= UpdateMaterial;
ColourManager.OnColourIndexChanged += UpdateMaterial;
// do the first update now with the current state
UpdateMaterial(ColourManager.colour);
}
// Now this is called only when the value is changed in the manager
// script and once at the beginning with the initial state
private void UpdateMaterial(int index)
{
// check for validity
if(index < 0 || index >= materials.Length) return;
_renderer.material = materials[index];
}
private void OnDestroy()
{
// Always make sure to clean up listeners once not needed anymore
// otherwise you get NullReferencExceptions
ColourManager.OnColourIndexChanged -= UpdateMaterial;
}
}