更改玩家对象颜色的问题

时间:2020-04-27 05:27:20

标签: c# unity3d

我正在制作一个小型平台游戏,在那儿,我制作了一个可以更改播放器颜色的场景。我制作了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];
        }
    }
}

1 个答案:

答案 0 :(得分:2)

  1. 请注意,更改sharedMaterial可能不是您要在此处执行的操作。

    如果要修改渲染器的材质,请使用材质。

    因此,请使用material。尤其是一次颜色已更改,并且您正在处理实例材质,此后更改共享材质完全无效。

  2. 然后不要在Update中执行此操作!设置每帧

  3. 最后请注意

    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;
    }
}
相关问题