Unity如何获取子游戏对象所有材质 实现受击闪红后恢复原材质
问题修复方案
核心问题
当前代码的核心问题是闪红结束后直接将材质颜色硬编码为白色,没有提前缓存物体所有子节点Renderer的初始材质颜色,导致原有材质被覆盖;另外当前协程等待时长仅为0.14秒,和要求的1秒闪红时长不匹配。
修复逻辑
- 闪红触发时第一时间缓存所有子物体Renderer的原始材质颜色
- 闪红等待时长调整为1秒
- 闪红结束后将材质颜色还原为之前缓存的初始值,而非设置为白色
- 增加空值判断,避免闪红过程中敌人被销毁触发空引用报错
修复后完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyHealth : MonoBehaviour { public float Health; public AudioSource Src; public AudioClip HurtClip; public GameObject DeathEffect; void Start() { Src = GameObject.Find("Main Camera").GetComponent<AudioSource>(); } public void TakeDamage(float amount) { StartCoroutine(FlashRed()); Src.PlayOneShot(HurtClip); Health -= amount; if (Health <= 0f) { Death(); } } void Death() { Instantiate(DeathEffect, transform.position, Quaternion.identity); Destroy(gameObject); } IEnumerator FlashRed() { // 获取所有子物体的渲染组件 Renderer[] renderers = GetComponentsInChildren<Renderer>(); // 缓存每个渲染器的原始材质颜色 Dictionary<Renderer, Color> originalColors = new Dictionary<Renderer, Color>(); foreach (Renderer rend in renderers) { // 存储原始颜色 originalColors.Add(rend, rend.material.color); // 设置为闪红色 rend.material.color = Color.red; } // 等待1秒,匹配闪红时长需求 yield return new WaitForSeconds(1f); // 还原原始颜色 foreach (Renderer rend in renderers) { // 空判定,避免闪红过程中物体被销毁触发报错 if (rend != null) { rend.material.color = originalColors[rend]; } } } }
额外注意事项
- 如果模型的Renderer上挂载了多个材质球,需要把缓存和修改逻辑调整为遍历
rend.materials数组,逐个缓存、修改、还原每个材质的颜色,否则只有第一个材质会闪红、还原 - 不要直接修改
sharedMaterial的颜色,否则会直接改动项目内的材质源文件,导致所有引用该材质的物体都被改色;修改material会自动生成运行时材质实例,改动仅作用于当前物体 - 如果需要支持连续受击时重置闪红计时,可以在启动协程前先停掉之前运行的
FlashRed协程,避免多协程同时运行导致颜色还原异常
内容的提问来源于stack exchange,提问作者Aseed Kid
相关产品推荐
相关产品推荐

