Misaki
demo是正常的 不好意思 我找到了原因 不过大概和SkeletonRenderer有一点点关系 urpInstance开启后 runtime下在shaderGUI上修改参数的时候 unity会自动给一个 material(instance) 这个时候修改material不会直接应用到资产上, 但是spine的renderer会一直去覆盖那个 材质 , 我专门做了一个shaderGui 方便runtime下进行调试
public class ShaderCustomerEditor:ShaderGUI
{
private const string DevelopInstanceKey = "ShaderCustomerEditor_DevelopInstance";
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
// Editor 模式使用基类
if (!Application.isPlaying)
{
// 在Editor直接使用基类的默认渲染
base.OnGUI(materialEditor, properties);
}
else
{
// 渲染开发模式开关
base.OnGUI(materialEditor, properties);
// 获取当前选中的对象
Object selectedObject = Selection.activeObject;
// 检查选中的对象是否是 GameObject
if (selectedObject is GameObject gameObject)
{
// 获取该 GameObject 的 Renderer
Renderer renderer = gameObject.GetComponent<Renderer>();
if (renderer==null)
{
return;
}
IRenderInstanceHelper instanceHelper = renderer.gameObject.GetComponent<IRenderInstanceHelper>();
if (instanceHelper == null)
{
return;
}
// 从 EditorPrefs 读取开发模式状态
bool developInstance = EditorPrefs.GetBool(DevelopInstanceKey, false);
developInstance = EditorGUILayout.Toggle("开发模式", developInstance);
// 保存状态到 EditorPrefs
EditorPrefs.SetBool(DevelopInstanceKey, developInstance);
if (developInstance)
{
foreach (var item in properties)
{
switch (item.type)
{
case MaterialProperty.PropType.Color:
// 获取颜色属性值
Color colorValue = instanceHelper.GetColor(item.name);
// 在 UI 上显示并允许编辑
Color newColorValue = EditorGUILayout.ColorField(item.displayName, colorValue);
// 只有在值变化时才更新
if (newColorValue != colorValue)
{
instanceHelper.SetColor(item.name, newColorValue);
}
break;
case MaterialProperty.PropType.Vector:
// 获取向量属性值
Vector4 vectorValue = instanceHelper.GetVector(item.name);
// 在 UI 上显示并允许编辑
Vector4 newVectorValue =
EditorGUILayout.Vector4Field(item.displayName, vectorValue);
// 只有在值变化时才更新
if (newVectorValue != vectorValue)
{
instanceHelper.SetVector(item.name, newVectorValue);
}
break;
case MaterialProperty.PropType.Float:
// 获取浮点数属性值
float floatValue = instanceHelper.GetFloat(item.name);
// 在 UI 上显示并允许编辑
float newFloatValue = EditorGUILayout.FloatField(item.displayName, floatValue);
// 只有在值变化时才更新
if (!Mathf.Approximately(newFloatValue, floatValue))
{
instanceHelper.SetFloat(item.name, newFloatValue);
}
break;
case MaterialProperty.PropType.Range:
// 获取范围属性值
float rangeValue = instanceHelper.GetFloat(item.name); // 假设范围也是浮点数
float minRange = item.rangeLimits.x; // 假设这些值已定义
float maxRange = item.rangeLimits.y;
// 在 UI 上显示并允许编辑
float newRangeValue = EditorGUILayout.Slider(item.displayName, rangeValue,
minRange, maxRange);
// 只有在值变化时才更新
if (!Mathf.Approximately(newRangeValue, rangeValue))
{
instanceHelper.SetFloat(item.name, newRangeValue);
}
break;
case MaterialProperty.PropType.Texture:
// 获取纹理属性值
Texture textureValue = instanceHelper.GetTexture(item.name);
// 在 UI 上显示并允许编辑
Texture newTextureValue = (Texture)EditorGUILayout.ObjectField(item.displayName,
textureValue, typeof(Texture), false);
// 只有在值变化时才更新
if (newTextureValue != textureValue)
{
instanceHelper.SetTexture(item.name, newTextureValue);
}
break;
default:
EditorGUILayout.LabelField(item.displayName, "未实现的属性类型");
break;
}
}
}
}
}
}
}
### 关于MaterialPropertyBlock部分
public class DefaultRenderInstanceHelper : MonoBehaviour, IRenderInstanceHelper
{
private Renderer _renderer;
private MaterialPropertyBlock[] _propertyBlocks;
private void Awake()
{
_renderer = GetComponent<Renderer>();
if (_renderer == null)
{
Debug.LogError("DefaultRenderInstanceHelper requires a Renderer component.");
}
// 初始化 MaterialPropertyBlock 数组,根据材质数量来决定大小
_propertyBlocks = new MaterialPropertyBlock[MaterialCount];
}
public int MaterialCount => _renderer != null ? _renderer.materials.Length : 0;
private MaterialPropertyBlock GetPropertyBlock(int materialIndex)
{
if (materialIndex < 0 || materialIndex >= MaterialCount)
{
throw new ArgumentOutOfRangeException(nameof(materialIndex), "Material index is out of range.");
}
// 如果尚未初始化该索引的 MaterialPropertyBlock,则创建一个新的
if (_propertyBlocks[materialIndex] == null)
{
_propertyBlocks[materialIndex] = new MaterialPropertyBlock();
}
// 从 Renderer 中加载现有属性
_renderer.GetPropertyBlock(_propertyBlocks[materialIndex], materialIndex);
return _propertyBlocks[materialIndex];
}
/// <summary>
/// 设置材质的属性块,并应用到 Renderer。
/// </summary>
private void ApplyPropertyBlock(int materialIndex)
{
_renderer.SetPropertyBlock(_propertyBlocks[materialIndex], materialIndex);
}
public void SetColor(string propertyName, Color color, int materialIndex = 0)
{
GetPropertyBlock(materialIndex).SetColor(propertyName, color);
ApplyPropertyBlock(materialIndex);
}
public void SetFloat(string propertyName, float value, int materialIndex = 0)
{
GetPropertyBlock(materialIndex).SetFloat(propertyName, value);
ApplyPropertyBlock(materialIndex);
}
public void SetVector(string propertyName, Vector4 vector, int materialIndex = 0)
{
GetPropertyBlock(materialIndex).SetVector(propertyName, vector);
ApplyPropertyBlock(materialIndex);
}
public void SetTexture(string propertyName, Texture texture, int materialIndex = 0)
{
GetPropertyBlock(materialIndex).SetTexture(propertyName, texture);
ApplyPropertyBlock(materialIndex);
}
public void SetMatrix(string propertyName, Matrix4x4 matrix, int materialIndex = 0)
{
GetPropertyBlock(materialIndex).SetMatrix(propertyName, matrix);
ApplyPropertyBlock(materialIndex);
}
public Color GetColor(string propertyName, int materialIndex = 0) =>
GetPropertyBlock(materialIndex).GetColor(propertyName);
public float GetFloat(string propertyName, int materialIndex = 0) =>
GetPropertyBlock(materialIndex).GetFloat(propertyName);
public Vector4 GetVector(string propertyName, int materialIndex = 0) =>
GetPropertyBlock(materialIndex).GetVector(propertyName);
public Texture GetTexture(string propertyName, int materialIndex = 0) =>
GetPropertyBlock(materialIndex).GetTexture(propertyName);
public Matrix4x4 GetMatrix(string propertyName, int materialIndex = 0) =>
GetPropertyBlock(materialIndex).GetMatrix(propertyName);
}
然后我发现了原因
gui在获取数据的时候 GetPropertyBlock(materialIndex).GetColor(propertyName);调用了renderer的 renderer.GetPropertyBlock(propertyBlocks[materialIndex], materialIndex);
这行代码导致 让renderer生成了一个新的材质 material(instance) skeletonRender中又一直覆盖shaderMaterial 无限递归就导致了上面视频的现象