This repository has been archived on 2025-09-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2023-11-08 13:41:11 +08:00

220 lines
4.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using XericLibrary.Runtime.MacroLibrary;
using XericLibrary.Runtime.Type;
using static UnityEngine.GraphicsBuffer;
namespace XericLibrary.Runtime.Generation
{
public class BaseGenerate<T> : WeaklyMonoBase
where T : WeaklyObject
{
#region 字段属性
/// <summary>
/// 生成器
/// </summary>
[SerializeField]
private T GenerationCompute;
#endregion
#region 生命周期
#endregion
#region 快捷静态
/// <summary>
/// 复制一个组件到另一个组件中
/// <code>
/// 这个方法只能用于 MonoBehaviours 或普通 C# 类的字段和属性,
/// 不能用于 Unity 内置组件(例如 Transform、Rigidbody 等)的复制,
/// 因为这些组件的字段和属性通常是私有的。
/// </code>
/// </summary>
/// <typeparam name="COMPONENT"></typeparam>
/// <param name="SOURCE"></param>
/// <param name="CopyTo"></param>
/// <returns></returns>
public static COMPONENT CopyComponentToAnother<COMPONENT>(COMPONENT source, COMPONENT copied)
where COMPONENT : Component
{
if(source == null || copied == null)
{
Debug.LogWarning("Source or target component is null. Cannot copy parameters.");
return null;
}
System.Type type = typeof(T);
var fields = type.GetFields();
var properties = type.GetProperties();
// 复制只考虑公共字段属性
foreach(var field in fields)
{
if(!field.IsStatic)
{
field.SetValue(copied, field.GetValue(source));
}
}
foreach(var property in properties)
{
if(property.CanWrite)
{
property.SetValue(copied, property.GetValue(source, null), null);
}
}
return copied;
}
/// <summary>
/// 从给定的物体上克隆一个组件到新的物体上
/// <code>
/// 这个方法适用于所有类型的组件
/// </code>
/// </summary>
/// <typeparam name="COMPONENT"></typeparam>
/// <param name="source"></param>
/// <param name="copied"></param>
/// <returns></returns>
public static COMPONENT CopyComponentToNew<COMPONENT>(GameObject source, out GameObject copied)
where COMPONENT : Component
{
Component[] allComponents = source.GetComponents<Component>();
copied = Instantiate(source);
foreach(Component component in copied.GetComponents<Component>())
{
if(component.GetType() != typeof(COMPONENT))
{
#if UNITY_EDITOR
if(PlayModeState != PlayModeStateChange.EnteredPlayMode)
DestroyImmediate(component);
else
Destroy(component);
#else
Destroy(component);
#endif
}
}
return copied.GetComponent<COMPONENT>();
}
#endregion
#region 快捷方法
/// <summary>
/// 创建节点
/// </summary>
protected GameObject CreatOrGetGameNode(string name, Transform parent = null)
{
var targetParent = parent == null ? transform : parent;
var node = targetParent.GetChildren()
.Where(a => a.name == name)
.Select(a => a.gameObject)
.FirstOrDefault();
if(node != null)
return node;
node = new GameObject(name);
node.transform.parent = targetParent;
return node;
}
/// <summary>
/// 使给定的游戏节点断子绝孙
/// </summary>
protected void DieSonless(Transform transform)
{
foreach(var target in transform.GetChildren().ToList())
{
#if UNITY_EDITOR
if(PlayModeState != PlayModeStateChange.EnteredPlayMode)
DestroyImmediate(target.gameObject);
else
Destroy(target.gameObject);
#else
Destroy(target.gameObject);
#endif
}
}
/// <summary>
/// 使给定的游戏节点断子绝孙
/// </summary>
protected void DieSonless(GameObject target)
{
DieSonless(target.transform);
}
/// <summary>
/// 提取所有组件,然后在同级中另起一个节点进行对指定组件结构的覆盖
/// </summary>
/// <typeparam name="COMPONENT"></typeparam>
/// <param name="transform">要提取组件的节点</param>
/// <param name="name">复制时另起节点的名称</param>
/// <param name="MaxStackDepth">最大检索深度</param>
protected void ExtractAllComponent<COMPONENT>(Transform transform, string name, int MaxStackDepth = 20)
where COMPONENT : Component
{
var root = CreatOrGetGameNode(name, transform);
DieSonless(root);
int index = 0;
// 提取组件
foreach(var comp in transform.GetComponentsInRecursionChildren<COMPONENT>(MaxStackDepth))
{
CreatOrGetGameNode($"component.{index++}", root.transform);
CopyComponentToNew<COMPONENT>(comp.gameObject, out var copiedObj);
copiedObj.transform.parent = root.transform;
}
}
#endregion
}
#if UNITY_EDITOR
/// <summary>
/// 基本的创建辅助器,用于在inspecter上创建按钮或其他功能
/// </summary>
public class BaseGenerateEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if(GUILayout.Button("生成更新"))
UpdateGen();
}
/// <summary>
/// 更新生成
/// </summary>
protected void UpdateGen()
{
var script = (StairsGenerate)target;
}
}
#endif
}