【问题标题】:Problem with changing the color of a game player object更改游戏玩家对象颜色的问题
【发布时间】:2020-04-27 17:39:57
【问题描述】:

我正在制作一个小型平台游戏,在其中,我制作了一个场景,您可以在其中更改播放器的颜色。我制作了 3 个按钮,当您单击它们时它们会改变颜色。我还制作了两个代码文件,但它们不起作用。我在控制台中也看不到任何错误。 P.S 变色代码和按钮与游戏对象位于不同的场景。

这是改变颜色的按钮的代码:

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];
        }
    }
}

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:
    1. 请注意,更改 sharedMaterial 可能不是您想要在此处执行的操作。

      如果您想修改渲染器的材质,请改用材质。

      所以宁愿使用material。尤其是一次,例如颜色已更改,您正在处理实例材质,之后更改共享材质完全没有效果。

    2. 那么不要在Update 中这样做! 每一帧都设置这个是非常多余和低效的!

    3. 最后要注意这个

      public int lcolour = ColourManager.colour;
      

      仅在此对象初始化时分配 ONCE,然后不再更改...intVALUE 类型,而不是引用!

      我宁愿使用 and 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;
        }
    }
    

    【讨论】:

    • 感谢您的解决方案,我非常感谢,但我也得到了这个解决方案。我将 int lcolor == ColourManager.colour 放在 void Update() 中,它工作得非常好。无论如何,非常感谢您的帮助。
    • @randomdev 如前所述.. 在Update 中执行此操作不是好的解决方案,而且相当多余,但您当然可以做您想做的事;)
    猜你喜欢
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多