(client) feat:添加UI多线段绘制器,贝塞尔曲线绘制器及其编辑器, fix:单目标子弹在一帧内击中多个目标未被限制击中数量
This commit is contained in:
3
Client/Assets/Editor.meta
Normal file
3
Client/Assets/Editor.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfd4e71629ef4332ad3e97a9b19a6574
|
||||
timeCreated: 1757414550
|
144
Client/Assets/Editor/UIBezierCurveGeneratorEditor.cs
Normal file
144
Client/Assets/Editor/UIBezierCurveGeneratorEditor.cs
Normal file
@ -0,0 +1,144 @@
|
||||
using UI;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
|
||||
// 告诉 Unity 这个编辑器是为 UIBezierCurveGenerator 组件服务的
|
||||
[CustomEditor(typeof(UIBezierCurveGenerator))]
|
||||
public class UIBezierCurveGeneratorEditor : UnityEditor.Editor
|
||||
{
|
||||
// 这个方法用于定义组件在 Inspector 窗口中的显示
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// 调用基类的 OnInspectorGUI 方法,绘制所有 public 或 [SerializeField] 字段
|
||||
// 这意味着我们会看到 P0, P1, P2, P3 和 segmentCount 的默认 Inspector 控件
|
||||
base.OnInspectorGUI();
|
||||
|
||||
// 获取目标组件的引用
|
||||
UIBezierCurveGenerator generator = (UIBezierCurveGenerator)target;
|
||||
|
||||
// 可以在这里添加自定义的 Inspector 按钮或信息
|
||||
if (GUILayout.Button("Generate Curve Now"))
|
||||
{
|
||||
generator.GenerateCurvePoints();
|
||||
}
|
||||
}
|
||||
|
||||
// 这个方法用于在 Scene 视图中绘制 Gizmos 或处理交互
|
||||
protected virtual void OnSceneGUI()
|
||||
{
|
||||
// 获取当前被选中的 UIBezierCurveGenerator 实例
|
||||
UIBezierCurveGenerator generator = (UIBezierCurveGenerator)target;
|
||||
RectTransform rectTransform = generator.GetComponent<RectTransform>();
|
||||
|
||||
// 如果没有 RectTransform 或 UILineRenderer,则无法操作,直接返回
|
||||
if (rectTransform == null || generator.lineRenderer == null) // lineRenderer 现已为 public
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保在 Scene 视图中显示时重新生成曲线
|
||||
// 这有助于在编辑器中实时预览,即使 Inspector 没有变动。
|
||||
// 但要注意,频繁调用 GenerateCurvePoints() 可能对性能有轻微影响,
|
||||
// 但对于贝塞尔曲线这种操作,通常是可以接受的。
|
||||
generator.GenerateCurvePoints();
|
||||
|
||||
|
||||
// 设置 Unity Editor Handles 的颜色,方便区分不同的点
|
||||
Handles.color = Color.white;
|
||||
// 修正:使用 HandleUtility.GetHandleSize 方法,并根据 P0 的世界位置计算句柄大小
|
||||
float handleSphereSize =
|
||||
HandleUtility.GetHandleSize(rectTransform.TransformPoint(generator.P0)) * 0.05f; // 调整一个合适的大小比例
|
||||
|
||||
// =========================================================
|
||||
// P0 (起点) 的操作
|
||||
// =========================================================
|
||||
Handles.color = Color.green; // 绿色表示起点
|
||||
Vector3 worldP0 = rectTransform.TransformPoint(generator.P0); // 将 P0 从局部坐标转换为世界坐标
|
||||
|
||||
EditorGUI.BeginChangeCheck(); // 开始检查是否有改变发生
|
||||
// 绘制一个可拖动的 PositionHandle,返回用户拖动后的新世界坐标
|
||||
worldP0 = Handles.PositionHandle(worldP0, Quaternion.identity);
|
||||
if (EditorGUI.EndChangeCheck()) // 如果 PositionHandle 被拖动,检测到改变
|
||||
{
|
||||
Undo.RecordObject(generator, "Move Bezier Point P0"); // 记录操作,支持撤销
|
||||
generator.P0 = rectTransform.InverseTransformPoint(worldP0); // 将新的世界坐标转换回局部坐标
|
||||
generator.GenerateCurvePoints(); // 立即更新曲线 (调用组件的方法)
|
||||
EditorUtility.SetDirty(generator); // 标记组件已修改,确保保存到场景
|
||||
}
|
||||
|
||||
Handles.DrawSolidDisc(worldP0, Vector3.forward, handleSphereSize * 0.8f); // 绘制一个小圆盘作为点标记
|
||||
|
||||
|
||||
// =========================================================
|
||||
// P1 (第一个控制点) 的操作
|
||||
// =========================================================
|
||||
Handles.color = Color.blue; // 蓝色表示第一个控制点
|
||||
Vector3 worldP1 = rectTransform.TransformPoint(generator.P1);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
worldP1 = Handles.PositionHandle(worldP1, Quaternion.identity);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(generator, "Move Bezier Point P1");
|
||||
generator.P1 = rectTransform.InverseTransformPoint(worldP1);
|
||||
generator.GenerateCurvePoints();
|
||||
EditorUtility.SetDirty(generator);
|
||||
}
|
||||
|
||||
Handles.DrawSolidDisc(worldP1, Vector3.forward, handleSphereSize * 0.6f);
|
||||
|
||||
|
||||
// =========================================================
|
||||
// P2 (第二个控制点) 的操作
|
||||
// =========================================================
|
||||
Handles.color = Color.magenta; // 洋红色表示第二个控制点
|
||||
Vector3 worldP2 = rectTransform.TransformPoint(generator.P2);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
worldP2 = Handles.PositionHandle(worldP2, Quaternion.identity);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(generator, "Move Bezier Point P2");
|
||||
generator.P2 = rectTransform.InverseTransformPoint(worldP2);
|
||||
generator.GenerateCurvePoints();
|
||||
EditorUtility.SetDirty(generator);
|
||||
}
|
||||
|
||||
Handles.DrawSolidDisc(worldP2, Vector3.forward, handleSphereSize * 0.6f);
|
||||
|
||||
|
||||
// =========================================================
|
||||
// P3 (终点) 的操作
|
||||
// =========================================================
|
||||
Handles.color = Color.red; // 红色表示终点
|
||||
Vector3 worldP3 = rectTransform.TransformPoint(generator.P3);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
worldP3 = Handles.PositionHandle(worldP3, Quaternion.identity);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(generator, "Move Bezier Point P3");
|
||||
generator.P3 = rectTransform.InverseTransformPoint(worldP3);
|
||||
generator.GenerateCurvePoints();
|
||||
EditorUtility.SetDirty(generator);
|
||||
}
|
||||
|
||||
Handles.DrawSolidDisc(worldP3, Vector3.forward, handleSphereSize * 0.8f);
|
||||
|
||||
|
||||
// =========================================================
|
||||
// 绘制辅助线 (控制杆),连接起点到第一个控制点,终点到第二个控制点
|
||||
// =========================================================
|
||||
Handles.color = Color.gray; // 灰色辅助线
|
||||
Handles.DrawLine(worldP0, worldP1); // P0 -> P1
|
||||
Handles.DrawLine(worldP2, worldP3); // P2 -> P3
|
||||
|
||||
// 刷新 Scene 视图,确保所有 Gizmos 和曲线更新立即显示
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1a4aaa124cb4e6c9d26f54bde32d674
|
||||
timeCreated: 1757418725
|
@ -176,7 +176,10 @@ MonoBehaviour:
|
||||
healthBarPrefab: {fileID: 8307348883874536545}
|
||||
entityPrefab: {fileID: 3332598847335032684}
|
||||
weaponAnimator: {fileID: 1007148524615441468}
|
||||
weaponItem: {fileID: 0}
|
||||
weaponAttackAnimation: {fileID: 0}
|
||||
direction: {x: 0, y: 0, z: 0}
|
||||
attackDirection: {x: 0, y: 0, z: 0}
|
||||
body: {fileID: 2838206730318674270}
|
||||
affiliation:
|
||||
canSelect: 1
|
||||
@ -246,6 +249,37 @@ Rigidbody2D:
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 4
|
||||
--- !u!1 &1007148524615441468
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4504455988891581487}
|
||||
m_Layer: 0
|
||||
m_Name: WeaponTexture
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4504455988891581487
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1007148524615441468}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 697189026367054479}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &2838206730318674270
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -366,70 +400,3 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 605f185650fe46d89a6e0d60fb8fb11c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1001 &5211884413447499418
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 697189026367054479}
|
||||
m_Modifications:
|
||||
- target: {fileID: 5021031438404678310, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: WeaponTexture
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
--- !u!1 &1007148524615441468 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 5021031438404678310, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
m_PrefabInstance: {fileID: 5211884413447499418}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!4 &4504455988891581487 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 8563418329714102965, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3}
|
||||
m_PrefabInstance: {fileID: 5211884413447499418}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
@ -873,6 +873,303 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1688506932
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1688506936}
|
||||
- component: {fileID: 1688506935}
|
||||
- component: {fileID: 1688506934}
|
||||
- component: {fileID: 1688506933}
|
||||
m_Layer: 5
|
||||
m_Name: Canvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1688506933
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1688506932}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!114 &1688506934
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1688506932}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 0
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 800, y: 600}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 0
|
||||
--- !u!223 &1688506935
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1688506932}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 1
|
||||
m_Camera: {fileID: 1057087089}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_VertexColorAlwaysGammaSpace: 0
|
||||
m_AdditionalShaderChannelsFlag: 25
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!224 &1688506936
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1688506932}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1813565768}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!1 &1802079591
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1802079592}
|
||||
m_Layer: 0
|
||||
m_Name: SkillTree
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1802079592
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1802079591}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 33.93411, y: 34.43715, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1813565767
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1813565768}
|
||||
- component: {fileID: 1813565770}
|
||||
- component: {fileID: 1813565769}
|
||||
- component: {fileID: 1813565771}
|
||||
m_Layer: 5
|
||||
m_Name: GameObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1813565768
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1813565767}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1688506936}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1813565769
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1813565767}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a7c56ce7d0f247639e5fff6ebba2edd6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
points:
|
||||
- {x: -133.03534, y: 73.06387}
|
||||
- {x: -88.07134, y: 68.2778}
|
||||
- {x: -52.80454, y: 62.199043}
|
||||
- {x: -25.609941, y: 55.11205}
|
||||
- {x: -5.077899, y: 47.27628}
|
||||
- {x: 10.005646, y: 38.927437}
|
||||
- {x: 20.67804, y: 30.27879}
|
||||
- {x: 27.817818, y: 21.522396}
|
||||
- {x: 32.16182, y: 12.830205}
|
||||
- {x: 34.321438, y: 4.355151}
|
||||
- {x: 34.797802, y: -3.7678308}
|
||||
- {x: 33.996346, y: -11.420871}
|
||||
- {x: 32.2403, y: -18.502266}
|
||||
- {x: 29.783356, y: -24.925674}
|
||||
- {x: 26.82156, y: -30.61938}
|
||||
- {x: 23.504032, y: -35.52555}
|
||||
- {x: 19.94323, y: -39.599724}
|
||||
- {x: 16.223877, y: -42.810104}
|
||||
- {x: 12.411441, y: -45.137222}
|
||||
- {x: 8.559343, y: -46.57335}
|
||||
- {x: 4.7155967, y: -47.122353}
|
||||
- {x: 0.9283457, y: -46.799118}
|
||||
- {x: -2.7493114, y: -45.6296}
|
||||
- {x: -6.2555466, y: -43.65044}
|
||||
- {x: -9.516719, y: -40.909004}
|
||||
- {x: -12.445361, y: -37.463264}
|
||||
- {x: -14.938893, y: -33.38188}
|
||||
- {x: -16.879314, y: -28.744246}
|
||||
- {x: -18.133726, y: -23.640694}
|
||||
- {x: -18.555773, y: -18.172682}
|
||||
- {x: -17.987919, y: -12.453108}
|
||||
- {x: -16.26463, y: -6.606659}
|
||||
- {x: -13.216493, y: -0.7702131}
|
||||
- {x: -8.675069, y: 4.9066596}
|
||||
- {x: -2.4787803, y: 10.261147}
|
||||
- {x: 5.5203714, y: 15.116601}
|
||||
- {x: 15.449296, y: 19.281828}
|
||||
- {x: 27.405247, y: 22.550373}
|
||||
- {x: 41.446537, y: 24.699694}
|
||||
- {x: 57.58231, y: 25.49029}
|
||||
- {x: 75.76138, y: 24.66478}
|
||||
- {x: 95.86027, y: 21.946861}
|
||||
- {x: 117.670395, y: 17.040276}
|
||||
- {x: 140.8842, y: 9.627667}
|
||||
- {x: 165.08054, y: -0.6306292}
|
||||
- {x: 189.70929, y: -14.097839}
|
||||
lineWidth: 5
|
||||
lineGradient:
|
||||
serializedVersion: 2
|
||||
key0: {r: 0.023668766, g: 1, b: 0, a: 1}
|
||||
key1: {r: 1, g: 1, b: 1, a: 1}
|
||||
key2: {r: 0, g: 0, b: 0, a: 0}
|
||||
key3: {r: 0, g: 0, b: 0, a: 0}
|
||||
key4: {r: 0, g: 0, b: 0, a: 0}
|
||||
key5: {r: 0, g: 0, b: 0, a: 0}
|
||||
key6: {r: 0, g: 0, b: 0, a: 0}
|
||||
key7: {r: 0, g: 0, b: 0, a: 0}
|
||||
ctime0: 0
|
||||
ctime1: 65535
|
||||
ctime2: 0
|
||||
ctime3: 0
|
||||
ctime4: 0
|
||||
ctime5: 0
|
||||
ctime6: 0
|
||||
ctime7: 0
|
||||
atime0: 0
|
||||
atime1: 65535
|
||||
atime2: 0
|
||||
atime3: 0
|
||||
atime4: 0
|
||||
atime5: 0
|
||||
atime6: 0
|
||||
atime7: 0
|
||||
m_Mode: 0
|
||||
m_ColorSpace: -1
|
||||
m_NumColorKeys: 2
|
||||
m_NumAlphaKeys: 2
|
||||
startCap: 2
|
||||
endCap: 2
|
||||
--- !u!222 &1813565770
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1813565767}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &1813565771
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1813565767}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8623ad98baf0495b8c8634232e3cae2e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
lineRenderer: {fileID: 1813565769}
|
||||
controlPoints:
|
||||
- {x: -133.03534, y: 73.06387}
|
||||
- {x: 245.0557, y: 42.776196}
|
||||
- {x: -155.57315, y: -95.5988}
|
||||
- {x: 171.73596, y: -95.63857}
|
||||
- {x: -196.53432, y: -28.766539}
|
||||
- {x: 5.0138226, y: 99.89391}
|
||||
- {x: 189.70929, y: -14.097839}
|
||||
segmentCount: 45
|
||||
--- !u!1 &2053271181
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -988,3 +1285,5 @@ SceneRoots:
|
||||
- {fileID: 1245790017}
|
||||
- {fileID: 593350052837672451}
|
||||
- {fileID: 178349937}
|
||||
- {fileID: 1802079592}
|
||||
- {fileID: 1688506936}
|
||||
|
@ -14,7 +14,7 @@ namespace Base
|
||||
}
|
||||
|
||||
// 自定义梯度效果类,继承自BaseMeshEffect
|
||||
public class Gradient : BaseMeshEffect
|
||||
public class ColorBar : BaseMeshEffect
|
||||
{
|
||||
[SerializeField] // 序列化字段,可在Inspector中编辑
|
||||
private Dir dir = Dir.Vertical; // 渐变方向,默认垂直
|
||||
|
@ -29,7 +29,7 @@ namespace Base
|
||||
/// 用于显示加载进度的自定义进度条组件。
|
||||
/// <para>请参阅类注释以了解其声明类型与预期API的差异。</para>
|
||||
/// </summary>
|
||||
public Gradient progressBar;
|
||||
public ColorBar progressBar;
|
||||
|
||||
/// <summary>
|
||||
/// 用于显示当前加载步骤描述的文本组件。
|
||||
|
@ -36,7 +36,7 @@ namespace Entity
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
var entity = other.GetComponent<Entity>();
|
||||
if (!entity || entity == bulletSource || entity is Pickup) return;
|
||||
if (IsDead||!entity || entity == bulletSource || entity is Pickup) return;
|
||||
if (Managers.AffiliationManager.Instance.GetRelation(bulletSource.affiliation, entity.affiliation) != Relation.Friendly || Setting.Instance.CurrentSettings.friendlyFire)
|
||||
{
|
||||
entity.OnHit(this);
|
||||
|
@ -216,6 +216,7 @@ namespace Entity
|
||||
return;
|
||||
weaponItem=GameObjectCreate.SpriteAnimator(currentWeapon.Icon.ToArray(), weaponAnimator.transform);
|
||||
weaponItem.SetFPS(currentWeapon.FPS);
|
||||
weaponItem.gameObject.SetActive(true);
|
||||
|
||||
weaponAttackAnimation = GameObjectCreate.SpriteAnimator(currentWeapon.AttackAnimation.ToArray(),
|
||||
weaponAnimator.transform);
|
||||
@ -393,7 +394,7 @@ namespace Entity
|
||||
private void StartAttack(WeaponResource weaponResource)
|
||||
{
|
||||
_attackTimer = weaponResource.AttackCooldown;
|
||||
_attackDetectionTime = weaponResource.AttackDetectionTime;
|
||||
_attackDetectionTime =Mathf.Max(0,weaponResource.AttackCooldown- weaponResource.AttackDetectionTime);
|
||||
currentAttackWeapon = weaponResource;
|
||||
|
||||
if (weaponResource.AttackAnimationTime > 0)
|
||||
@ -594,8 +595,13 @@ namespace Entity
|
||||
{
|
||||
var mousePos = MousePosition.GetWorldPosition();
|
||||
attackDirection = new Vector3(mousePos.x,mousePos.y) - Position;
|
||||
RotateTool.RotateTransformToDirection(weaponItem.transform, attackDirection);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.V))
|
||||
{
|
||||
weaponItem.gameObject.SetActive(!weaponItem.gameObject.activeSelf);
|
||||
}
|
||||
|
||||
// 获取当前键盘输入状态(2D 移动,只使用 X 和 Y 轴)
|
||||
var inputDirection = Vector2.zero;
|
||||
|
||||
|
7
Client/Assets/Scripts/Prefab/SkillTreeNodeProfab.cs
Normal file
7
Client/Assets/Scripts/Prefab/SkillTreeNodeProfab.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Prefab
|
||||
{
|
||||
public class SkillTreeNodeProfab
|
||||
{
|
||||
|
||||
}
|
||||
}
|
3
Client/Assets/Scripts/Prefab/SkillTreeNodeProfab.cs.meta
Normal file
3
Client/Assets/Scripts/Prefab/SkillTreeNodeProfab.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78843bef7bb2445495588f60349626d9
|
||||
timeCreated: 1757395333
|
148
Client/Assets/Scripts/UI/UIBezierCurveGenerator.cs
Normal file
148
Client/Assets/Scripts/UI/UIBezierCurveGenerator.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
// 需要引用 UILineRenderer 组件
|
||||
[RequireComponent(typeof(UILineRenderer))]
|
||||
// 允许在编辑器模式下实时更新,便于调试
|
||||
[ExecuteAlways]
|
||||
public class UIBezierCurveGenerator : MonoBehaviour
|
||||
{
|
||||
// UILineRenderer 组件的引用
|
||||
[SerializeField] public UILineRenderer lineRenderer;
|
||||
|
||||
// 控制点
|
||||
[Header("Bezier Control Points")] public Vector2 P0; // 起点
|
||||
public Vector2 P1; // 第一个控制点
|
||||
public Vector2 P2; // 第二个控制点
|
||||
public Vector2 P3; // 终点
|
||||
|
||||
[Header("Curve Settings")] [Range(5, 200)] // 限制段数范围,防止过低导致不平滑,过高导致性能问题
|
||||
public int segmentCount = 50; // 曲线的平滑度,即采样的线段数量
|
||||
|
||||
void Awake()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
Initialize();
|
||||
if (lineRenderer != null)
|
||||
{
|
||||
GenerateCurvePoints(); // 在编辑器中修改参数时实时更新曲线
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化组件,获取 UILineRenderer 引用
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
lineRenderer = GetComponent<UILineRenderer>();
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
Debug.LogError("UILineRenderer component not found on this GameObject. Please add one.", this);
|
||||
enabled = false; // 禁用此组件,防止空引用错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算三次贝塞尔曲线上的点
|
||||
/// B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + 3 * (1-t) * t^2 * P2 + t^3 * P3
|
||||
/// </summary>
|
||||
/// <param name="t">参数,范围 [0, 1]</param>
|
||||
/// <param name="p0">起点</param>
|
||||
/// <param name="p1">第一个控制点</param>
|
||||
/// <param name="p2">第二个控制点</param>
|
||||
/// <param name="p3">终点</param>
|
||||
/// <returns>在参数 t 处的贝塞尔曲线上点</returns>
|
||||
private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
|
||||
{
|
||||
float u = 1 - t;
|
||||
float tt = t * t;
|
||||
float uu = u * u;
|
||||
float uuu = uu * u;
|
||||
float ttt = tt * t;
|
||||
|
||||
Vector2 p = uuu * p0; // (1-t)^3 * P0
|
||||
p += 3 * uu * t * p1; // 3 * (1-t)^2 * t * P1
|
||||
p += 3 * u * tt * p2; // 3 * (1-t) * t^2 * P2
|
||||
p += ttt * p3; // t^3 * P3
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成贝塞尔曲线的点并更新 UILineRenderer
|
||||
/// </summary>
|
||||
public void GenerateCurvePoints()
|
||||
{
|
||||
if (lineRenderer == null || segmentCount <= 0)
|
||||
{
|
||||
Debug.LogWarning("UILineRenderer is null or segmentCount is invalid. Cannot generate curve.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
// 清空 UILineRenderer 的点列表,以便重新填充
|
||||
lineRenderer.points.Clear();
|
||||
|
||||
for (int i = 0; i <= segmentCount; i++)
|
||||
{
|
||||
float t = i / (float)segmentCount;
|
||||
Vector2 point = CalculateBezierPoint(t, P0, P1, P2, P3);
|
||||
lineRenderer.points.Add(point);
|
||||
}
|
||||
|
||||
// 通知 UILineRenderer 需要重新绘制其几何体
|
||||
lineRenderer.SetAllDirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提供了通过代码设置控制点并刷新曲线的方法
|
||||
/// </summary>
|
||||
public void SetControlPoints(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
|
||||
{
|
||||
this.P0 = p0;
|
||||
this.P1 = p1;
|
||||
this.P2 = p2;
|
||||
this.P3 = p3;
|
||||
GenerateCurvePoints();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提供了通过代码设置曲线段数并刷新曲线的方法
|
||||
/// </summary>
|
||||
public void SetSegmentCount(int count)
|
||||
{
|
||||
segmentCount = Mathf.Max(5, count); // 至少保留5段,保证一定平滑度
|
||||
GenerateCurvePoints();
|
||||
}
|
||||
|
||||
// 当组件首次添加或重置时调用
|
||||
void Reset()
|
||||
{
|
||||
Initialize(); // 确保 lineRenderer 已初始化
|
||||
|
||||
// 根据 RectTransform 的大小设置默认点,确保在可见范围内
|
||||
RectTransform rt = GetComponent<RectTransform>();
|
||||
float halfWidth = rt.rect.width / 2f;
|
||||
float halfHeight = rt.rect.height / 2f;
|
||||
|
||||
// 设置一些默认的控制点,让曲线在UI区域内可见
|
||||
// 这些是相对于 RectTransform 的局部坐标
|
||||
P0 = new Vector2(-halfWidth * 0.8f, -halfHeight * 0.5f); // 左下
|
||||
P1 = new Vector2(-halfWidth * 0.4f, halfHeight * 0.8f); // 左上控制点
|
||||
P2 = new Vector2(halfWidth * 0.4f, halfHeight * 0.8f); // 右上控制点
|
||||
P3 = new Vector2(halfWidth * 0.8f, -halfHeight * 0.5f); // 右下
|
||||
|
||||
segmentCount = 50;
|
||||
|
||||
GenerateCurvePoints(); // 立即生成曲线
|
||||
}
|
||||
}
|
||||
|
||||
}
|
3
Client/Assets/Scripts/UI/UIBezierCurveGenerator.cs.meta
Normal file
3
Client/Assets/Scripts/UI/UIBezierCurveGenerator.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8623ad98baf0495b8c8634232e3cae2e
|
||||
timeCreated: 1757418458
|
439
Client/Assets/Scripts/UI/UILineRenderer.cs
Normal file
439
Client/Assets/Scripts/UI/UILineRenderer.cs
Normal file
@ -0,0 +1,439 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static UI.UILineRenderer; // 允许LineCapType直接访问
|
||||
|
||||
// 确保在UI命名空间内
|
||||
namespace UI
|
||||
{
|
||||
/// <summary>
|
||||
/// UILineRenderer 是一个用于在UI中绘制自定义线条的Graphic组件。
|
||||
/// 它支持设置线条宽度、渐变颜色以及不同类型的线头(方形或圆形)。
|
||||
/// 同时支持线段之间的斜切连接,以确保转角平滑。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public class UILineRenderer : Graphic
|
||||
{
|
||||
/// <summary>
|
||||
/// 存储构成线条的顶点列表。
|
||||
/// </summary>
|
||||
public List<Vector2> points = new List<Vector2>();
|
||||
|
||||
/// <summary>
|
||||
/// 线的宽度。
|
||||
/// </summary>
|
||||
[SerializeField] private float lineWidth = 5f;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置线的宽度。
|
||||
/// 设置新值时,如果宽度发生改变,将触发UI网格的重新绘制。
|
||||
/// </summary>
|
||||
public float LineWidth
|
||||
{
|
||||
get => lineWidth;
|
||||
set
|
||||
{
|
||||
// 仅当值发生显著变化时才更新,以避免不必要的重绘。
|
||||
// Mathf.Abs(lineWidth - value) > float.Epsilon 是一个更健壮的浮点数比较方式。
|
||||
if (Mathf.Abs(lineWidth - value) > float.Epsilon)
|
||||
{
|
||||
lineWidth = value;
|
||||
SetVerticesDirty(); // 标记UI网格需要重新生成。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于线条的渐变颜色。
|
||||
/// </summary>
|
||||
public Gradient lineGradient = new Gradient();
|
||||
|
||||
/// <summary>
|
||||
/// 定义线条两端的线头类型。
|
||||
/// </summary>
|
||||
public enum LineCapType
|
||||
{
|
||||
/// <summary>
|
||||
/// 无线头。
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// 方形线头。
|
||||
/// </summary>
|
||||
Square,
|
||||
/// <summary>
|
||||
/// 圆形线头。
|
||||
/// </summary>
|
||||
Round
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 线的起始端线头类型。
|
||||
/// </summary>
|
||||
public LineCapType startCap = LineCapType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 线的结束端线头类型。
|
||||
/// </summary>
|
||||
public LineCapType endCap = LineCapType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于UI渲染的相机。
|
||||
/// 如果Canvas的渲染模式是Screen Space - Overlay,则返回null,此时不需要相机。
|
||||
/// </summary>
|
||||
/// <returns>用于UI渲染的Camera实例,或在Overlay模式下返回null。</returns>
|
||||
private Camera GetCanvasRenderCamera()
|
||||
{
|
||||
Canvas _canvas = GetComponentInParent<Canvas>();
|
||||
// 作为Graphic组件,总会有一个Canvas作为父级。
|
||||
if (_canvas == null) return null;
|
||||
// 对于ScreenSpaceOverlay模式,不需要相机来将屏幕点转换为世界点。
|
||||
return _canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : _canvas.worldCamera;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在UI需要被重新绘制时调用,用于生成网格顶点数据。
|
||||
/// </summary>
|
||||
/// <param name="vh">VertexHelper,用于构建UI元素的网格。</param>
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
vh.Clear();
|
||||
|
||||
// 如果点列表为空或点的数量不足以构成线段,则不绘制任何东西。
|
||||
if (points == null || points.Count < 2)
|
||||
return;
|
||||
|
||||
// 如果渐变色对象未设置或颜色键为空,则默认创建一个纯白色渐变。
|
||||
if (lineGradient == null || lineGradient.colorKeys.Length == 0)
|
||||
{
|
||||
lineGradient = new Gradient();
|
||||
lineGradient.SetKeys(
|
||||
new[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
|
||||
new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) }
|
||||
);
|
||||
}
|
||||
|
||||
List<float> segmentLengths = new List<float>();
|
||||
float totalLength = 0f;
|
||||
|
||||
// 预计算线条总长度和每段长度,用于渐变色和线头定位
|
||||
for (int i = 0; i < points.Count - 1; i++)
|
||||
{
|
||||
float len = Vector2.Distance(points[i], points[i + 1]);
|
||||
segmentLengths.Add(len);
|
||||
totalLength += len;
|
||||
}
|
||||
|
||||
// 存储计算出的所有顶点,包括内外侧及颜色信息
|
||||
List<UIVertex> vertices = new List<UIVertex>();
|
||||
|
||||
float currentRenderedLength = 0f;
|
||||
float halfWidth = lineWidth / 2f;
|
||||
const float miterLimit = 4f; // Miter limit to prevent excessively long miters
|
||||
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
Vector2 p = points[i];
|
||||
Vector2 currentPerp = Vector2.zero; // 垂直于期望线段方向的偏移向量
|
||||
|
||||
// 计算当前点的渐变颜色
|
||||
float normalizedDistance = (totalLength > 0 && points.Count > 1) ? (currentRenderedLength / totalLength) : 0f;
|
||||
Color pointColor = lineGradient.Evaluate(normalizedDistance);
|
||||
|
||||
if (i == 0) // 第一个点 (起点)
|
||||
{
|
||||
// 使用第一段的法线方向
|
||||
Vector2 segmentDir = (points[1] - p).normalized;
|
||||
currentPerp = new Vector2(-segmentDir.y, segmentDir.x) * halfWidth;
|
||||
}
|
||||
else if (i == points.Count - 1) // 最后一个点 (终点)
|
||||
{
|
||||
// 使用最后一段的法线方向
|
||||
Vector2 segmentDir = (p - points[points.Count - 2]).normalized;
|
||||
currentPerp = new Vector2(-segmentDir.y, segmentDir.x) * halfWidth;
|
||||
}
|
||||
else // 中间点 (转角)
|
||||
{
|
||||
Vector2 prevDir = (p - points[i - 1]).normalized;
|
||||
Vector2 nextDir = (points[i + 1] - p).normalized;
|
||||
|
||||
// 计算两条线段的平均法线 (角平分线方向)
|
||||
Vector2 angleBisector = (prevDir + nextDir).normalized;
|
||||
|
||||
// 计算垂直于角平分线的向量
|
||||
Vector2 bisectorPerp = new Vector2(-angleBisector.y, angleBisector.x);
|
||||
|
||||
// 确定 bisectorPerp 的方向,使其始终指向“外侧”
|
||||
// 通过检查 prevDir 和 bisectorPerp 的点积来判断方向
|
||||
// 如果点积为负,表示 prevDir 的“向左”方向(perp)与 bisectorPerp 方向相反,需要翻转
|
||||
// (prevDir.x * bisectorPerp.y - prevDir.y * bisectorPerp.x) > 0 表示 bisectorPerp 在 prevDir 的左侧
|
||||
// (prevDir.x * bisectorPerp.y - prevDir.y * bisectorPerp.x) < 0 表示 bisectorPerp 在 prevDir 的右侧
|
||||
// 更直观的判断是看prevDir的右向量和bisectorPerp是否同向
|
||||
Vector2 prevDirPerp = new Vector2(-prevDir.y, prevDir.x); // prevDir的左侧法线
|
||||
if (Vector2.Dot(prevDirPerp, bisectorPerp) < 0) // 如果bisectorPerp不是指向prevDir左侧,则翻转
|
||||
{
|
||||
bisectorPerp *= -1;
|
||||
}
|
||||
|
||||
// 计算斜切的延伸长度
|
||||
// 角度越尖锐,cos(angle/2) 越小,miterFactor 越大
|
||||
float angleRad = Vector2.Angle(prevDir, nextDir) * Mathf.Deg2Rad;
|
||||
float miterLengthFactor = halfWidth / Mathf.Max(0.001f, Mathf.Cos(angleRad / 2f)); // 防止除以0
|
||||
|
||||
// 应用miter limit,避免极端尖锐角造成过长斜切
|
||||
miterLengthFactor = Mathf.Min(miterLengthFactor, lineWidth * miterLimit);
|
||||
|
||||
currentPerp = bisectorPerp * miterLengthFactor;
|
||||
}
|
||||
|
||||
// 添加内外侧顶点
|
||||
// Outer point
|
||||
vertices.Add(new UIVertex
|
||||
{
|
||||
position = p + currentPerp,
|
||||
color = pointColor,
|
||||
uv0 = new Vector2(0, normalizedDistance) // Simple UV mapping for gradient, 0 for outer
|
||||
});
|
||||
// Inner point
|
||||
vertices.Add(new UIVertex
|
||||
{
|
||||
position = p - currentPerp,
|
||||
color = pointColor,
|
||||
uv0 = new Vector2(1, normalizedDistance) // Simple UV mapping for gradient, 1 for inner
|
||||
});
|
||||
|
||||
// 更新已渲染长度,用于下一个点的渐变计算
|
||||
if (i < segmentLengths.Count)
|
||||
{
|
||||
currentRenderedLength += segmentLengths[i];
|
||||
}
|
||||
}
|
||||
|
||||
// --- 绘制线段网格 ---
|
||||
for (int i = 0; i < points.Count - 1; i++)
|
||||
{
|
||||
int prevOuter = i * 2; // 上一个点的外侧顶点索引
|
||||
int prevInner = i * 2 + 1; // 上一个点的内侧顶点索引
|
||||
int currentOuter = (i + 1) * 2; // 当前点的外侧顶点索引
|
||||
int currentInner = (i + 1) * 2 + 1; // 当前点的内侧顶点索引
|
||||
|
||||
// 添加顶点到 VertexHelper
|
||||
// 确保vh.AddVert的顺序与vertices列表中的顺序一致
|
||||
if (i == 0) // 为第一个点添加顶点
|
||||
{
|
||||
vh.AddVert(vertices[prevOuter]);
|
||||
vh.AddVert(vertices[prevInner]);
|
||||
}
|
||||
vh.AddVert(vertices[currentOuter]);
|
||||
vh.AddVert(vertices[currentInner]);
|
||||
|
||||
// 连接当前点和上一个点的顶点,形成一个矩形(两个三角形)
|
||||
vh.AddTriangle(prevOuter, currentOuter, currentInner);
|
||||
vh.AddTriangle(prevOuter, currentInner, prevInner);
|
||||
}
|
||||
|
||||
// --- 绘制线头 ---
|
||||
if (points.Count >= 2)
|
||||
{
|
||||
// 起点线头
|
||||
Vector2 firstSegmentDirection = (points[1] - points[0]).normalized;
|
||||
DrawCap(vh, points[0], -firstSegmentDirection, startCap, lineGradient.Evaluate(0f));
|
||||
|
||||
// 终点线头
|
||||
Vector2 lastSegmentDirection = (points[points.Count - 1] - points[points.Count - 2]).normalized;
|
||||
DrawCap(vh, points[points.Count - 1], lastSegmentDirection, endCap, lineGradient.Evaluate(1f));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制指定类型的线头。
|
||||
/// </summary>
|
||||
/// <param name="vh">VertexHelper,用于构建线头网格。</param>
|
||||
/// <param name="center">线头的中心(即线条的端点)。</param>
|
||||
/// <param name="direction">线头延伸的方向。</param>
|
||||
/// <param name="capType">线头类型(无、方形或圆形)。</param>
|
||||
/// <param name="capColor">线头的颜色。</param>
|
||||
private void DrawCap(VertexHelper vh, Vector2 center, Vector2 direction, LineCapType capType, Color capColor)
|
||||
{
|
||||
if (capType == LineCapType.None) return;
|
||||
|
||||
// 计算线头垂直于方向的向量,用于确定线头的宽度。
|
||||
var perpendicular = new Vector2(-direction.y, direction.x) * lineWidth / 2f;
|
||||
// 记录当前VertexHelper中的顶点数量。
|
||||
var currentVertCount = vh.currentVertCount;
|
||||
|
||||
UIVertex vertexTemplate = UIVertex.simpleVert;
|
||||
vertexTemplate.color = capColor;
|
||||
|
||||
if (capType == LineCapType.Square)
|
||||
{
|
||||
// 绘制方形线头,通过在端点处添加一个与线段垂直的矩形。
|
||||
Vector2 p0 = center - perpendicular; // 线段边缘点1
|
||||
Vector2 p1 = center + perpendicular; // 线段边缘点2
|
||||
Vector2 p2 = center + perpendicular + (direction * (lineWidth / 2f)); // 延伸点1
|
||||
Vector2 p3 = center - perpendicular + (direction * (lineWidth / 2f)); // 延伸点2
|
||||
|
||||
// 添加方形线头的四个顶点。
|
||||
// 注意:这里需要确保顶点的顺序正确,形成两个三角形
|
||||
vertexTemplate.position = p0; vertexTemplate.uv0 = new Vector2(0f, 0f); vh.AddVert(vertexTemplate); // 0
|
||||
vertexTemplate.position = p1; vertexTemplate.uv0 = new Vector2(1f, 0f); vh.AddVert(vertexTemplate); // 1
|
||||
vertexTemplate.position = p2; vertexTemplate.uv0 = new Vector2(1f, 1f); vh.AddVert(vertexTemplate); // 2
|
||||
vertexTemplate.position = p3; vertexTemplate.uv0 = new Vector2(0f, 1f); vh.AddVert(vertexTemplate); // 3
|
||||
|
||||
// 添加两个三角形组成方形线头。
|
||||
vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
|
||||
vh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
|
||||
}
|
||||
else if (capType == LineCapType.Round)
|
||||
{
|
||||
const int segments = 12; // 增加段数使圆形更平滑
|
||||
float radius = lineWidth / 2f; // 半圆的半径等于线宽的一半。
|
||||
|
||||
// 添加扇形中心点。
|
||||
vertexTemplate.position = center;
|
||||
vertexTemplate.uv0 = new Vector2(0.5f, 0.5f); // 中心UV
|
||||
vh.AddVert(vertexTemplate);
|
||||
var centerVertIndex = currentVertCount;
|
||||
currentVertCount++;
|
||||
|
||||
// 计算半圆弧的起始角度 (垂直向量的角度) 和每段的扫过角度。
|
||||
float baseAngle = Mathf.Atan2(perpendicular.y, perpendicular.x);
|
||||
float angleSweepStep = Mathf.PI / segments; // 180度 / 段数。
|
||||
|
||||
List<int> arcVerticesIndices = new List<int>();
|
||||
|
||||
// 遍历并添加半圆弧上的点。
|
||||
for (int j = 0; j <= segments; j++)
|
||||
{
|
||||
float angle = baseAngle - (j * angleSweepStep); // 逆时针扫描。
|
||||
Vector2 pointOnArc = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * radius;
|
||||
|
||||
vertexTemplate.position = center + pointOnArc;
|
||||
// 计算相对中心的UV,使纹理正确映射到圆形。
|
||||
vertexTemplate.uv0 = new Vector2(0.5f + pointOnArc.x / (radius * 2), 0.5f + pointOnArc.y / (radius * 2));
|
||||
vh.AddVert(vertexTemplate);
|
||||
arcVerticesIndices.Add(currentVertCount);
|
||||
currentVertCount++;
|
||||
}
|
||||
|
||||
// 连接扇形中心和弧上的相邻点形成三角形,构成半圆形线头。
|
||||
for (int j = 0; j < arcVerticesIndices.Count - 1; j++)
|
||||
{
|
||||
vh.AddTriangle(centerVertIndex, arcVerticesIndices[j], arcVerticesIndices[j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将一个UI元素的世界坐标转换为此UILineRenderer的局部坐标,并将其作为线条上的一个点添加。
|
||||
/// </summary>
|
||||
/// <param name="uiElement">要作为线条点的RectTransform UI元素。</param>
|
||||
public void AppendUIElement(RectTransform uiElement)
|
||||
{
|
||||
Vector2 localPoint; // 转换后的局部坐标。
|
||||
|
||||
// 将UI元素的世界坐标转换为屏幕坐标,再将屏幕坐标转换为当前UILineRenderer的局部坐标。
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
rectTransform, // 当前 UILineRenderer 的 RectTransform。
|
||||
RectTransformUtility.WorldToScreenPoint(GetCanvasRenderCamera(), uiElement.position), // UI 元素的世界坐标转换为屏幕坐标。
|
||||
GetCanvasRenderCamera(), // 使用正确的相机进行屏幕到局部坐标转换。
|
||||
out localPoint // 输出的局部坐标。
|
||||
);
|
||||
|
||||
// 添加转换后的局部坐标到点列表中。
|
||||
points.Add(localPoint);
|
||||
|
||||
SetVerticesDirty(); // 标记UI网格需要重新生成。
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将鼠标的当前位置作为线条的末端点。
|
||||
/// 该方法支持对已有折线的末端点进行修改,也可用于绘制“橡皮筋”效果。
|
||||
/// </summary>
|
||||
public void SetMouse()
|
||||
{
|
||||
// 如果点列表为空,则无法设置鼠标位置为末端点,直接返回。
|
||||
if (points.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mousePosition = Input.mousePosition; // 获取当前的鼠标屏幕坐标。
|
||||
Vector2 localPoint;
|
||||
|
||||
// 将鼠标屏幕坐标转换为当前UILineRenderer的局部坐标。
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, mousePosition, GetCanvasRenderCamera(), out localPoint);
|
||||
|
||||
if (points.Count == 1)
|
||||
{
|
||||
// 如果只有一个点,则将鼠标位置作为第二点添加到列表,形成第一条线段。
|
||||
points.Add(localPoint);
|
||||
}
|
||||
else // points.Count >= 2
|
||||
{
|
||||
// 如果已有多个点,则更新列表中的最后一个点为鼠标位置。
|
||||
points[points.Count - 1] = localPoint;
|
||||
}
|
||||
|
||||
SetVerticesDirty(); // 标记UI网格需要重新生成。
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置线的宽度。
|
||||
/// </summary>
|
||||
/// <param name="width">线条的新宽度。</param>
|
||||
public void SetWidth(float width)
|
||||
{
|
||||
LineWidth = width; // 调用公共属性,确保 SetVerticesDirty() 被调用。
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置线条的渐变颜色。
|
||||
/// </summary>
|
||||
/// <param name="newGradient">新的渐变色对象。</param>
|
||||
public void SetGradient(Gradient newGradient)
|
||||
{
|
||||
// 仅当新的渐变色不同于当前渐变色时才进行更新。
|
||||
if (newGradient != null && !newGradient.Equals(lineGradient))
|
||||
{
|
||||
lineGradient = newGradient;
|
||||
SetVerticesDirty(); // 标记UI网格需要重新生成。
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置线条的起始和结束线头类型。
|
||||
/// </summary>
|
||||
/// <param name="startCapType">新的起始线头类型。</param>
|
||||
/// <param name="endCapType">新的结束线头类型。</param>
|
||||
public void SetCaps(LineCapType startCapType, LineCapType endCapType)
|
||||
{
|
||||
// 仅当线头类型发生改变时才更新。
|
||||
if (startCap != startCapType || endCap != endCapType)
|
||||
{
|
||||
startCap = startCapType;
|
||||
endCap = endCapType;
|
||||
SetVerticesDirty(); // 标记UI网格需要重新生成。
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置此UILineRenderer组件的状态,包括清空所有点、重置宽度、渐变色和线头类型。
|
||||
/// </summary>
|
||||
public void ResetSelf()
|
||||
{
|
||||
points.Clear(); // 清空所有线条点。
|
||||
// 重置为默认的纯白色渐变。
|
||||
lineGradient = new Gradient();
|
||||
lineGradient.SetKeys(
|
||||
new[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
|
||||
new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) }
|
||||
);
|
||||
lineWidth = 5f; // 重置线条宽度为默认值。
|
||||
startCap = LineCapType.None; // 重置线头类型为无。
|
||||
endCap = LineCapType.None; // 重置线头类型为无。
|
||||
SetVerticesDirty(); // 标记UI网格需要重新生成。
|
||||
}
|
||||
}
|
||||
}
|
3
Client/Assets/Scripts/UI/UILineRenderer.cs.meta
Normal file
3
Client/Assets/Scripts/UI/UILineRenderer.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7c56ce7d0f247639e5fff6ebba2edd6
|
||||
timeCreated: 1757415509
|
@ -26,7 +26,7 @@
|
||||
<defName>TestGun</defName>
|
||||
<attack>10</attack>
|
||||
<defense>3</defense>
|
||||
<attackSpeed>3</attackSpeed>
|
||||
<attackSpeed>1</attackSpeed>
|
||||
<attackRange>10</attackRange>
|
||||
<attackTargetCount>1</attackTargetCount>
|
||||
</AttributesDef>
|
||||
@ -38,7 +38,7 @@
|
||||
<!-- 引用属性定义 -->
|
||||
<attributes>TestGun</attributes>
|
||||
<type>Ranged</type>
|
||||
<FPS>2</FPS>
|
||||
<FPS>10</FPS>
|
||||
<textures>
|
||||
<li>TestGunItem</li>
|
||||
</textures>
|
||||
@ -54,7 +54,7 @@
|
||||
<li>testGunAttackAnimation_8</li>
|
||||
<li>testGunAttackAnimation_9</li>
|
||||
</attackAnimation>
|
||||
<attackDetectionTime>2.5</attackDetectionTime>
|
||||
<attackDetectionTime>0.5</attackDetectionTime>
|
||||
<maxStack>1</maxStack>
|
||||
<rarity>Uncommon</rarity>
|
||||
<attackDetectionTime>0.3</attackDetectionTime>
|
||||
|
@ -20,7 +20,7 @@
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<moveSpeed>1</moveSpeed>
|
||||
<health>123</health>
|
||||
<health>2</health> <!-- 123 -> approx 2 (round down) -->
|
||||
</attributes>
|
||||
<weapon>Claw</weapon>
|
||||
<drawingOrder>
|
||||
@ -46,7 +46,7 @@
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<moveSpeed>1</moveSpeed>
|
||||
<health>123</health>
|
||||
<health>2</health> <!-- 123 -> approx 2 (round down) -->
|
||||
</attributes>
|
||||
<weapon>TestGun</weapon>
|
||||
<drawingOrder>
|
||||
@ -72,8 +72,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>4600</health>
|
||||
<defense>100</defense>
|
||||
<health>60</health> <!-- 4600 -> 60 (scaled) -->
|
||||
<defense>10</defense> <!-- 100 -> 10 -->
|
||||
<moveSpeed>2.5</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterA1</weapon>
|
||||
@ -107,8 +107,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>6000</health>
|
||||
<defense>10</defense>
|
||||
<health>80</health> <!-- 6000 -> 80 (scaled) -->
|
||||
<defense>1</defense> <!-- 10 -> 1 -->
|
||||
<moveSpeed>4</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterA2</weapon>
|
||||
@ -142,8 +142,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>5000</health>
|
||||
<defense>400</defense>
|
||||
<health>70</health> <!-- 5000 -> 70 (scaled) -->
|
||||
<defense>40</defense> <!-- 400 -> 40 -->
|
||||
<moveSpeed>1</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterB1</weapon>
|
||||
@ -177,8 +177,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>8000</health>
|
||||
<defense>500</defense>
|
||||
<health>100</health> <!-- 8000 -> 100 (scaled) -->
|
||||
<defense>50</defense> <!-- 500 -> 50 -->
|
||||
<moveSpeed>1.5</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterB2</weapon>
|
||||
@ -212,8 +212,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>22000</health>
|
||||
<defense>800</defense>
|
||||
<health>300</health> <!-- 22000 -> 300 (scaled) -->
|
||||
<defense>80</defense> <!-- 800 -> 80 -->
|
||||
<moveSpeed>1</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterC1</weapon>
|
||||
@ -247,8 +247,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>22000</health>
|
||||
<defense>450</defense>
|
||||
<health>300</health> <!-- 22000 -> 300 (scaled) -->
|
||||
<defense>45</defense> <!-- 450 -> 45 -->
|
||||
<moveSpeed>2</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterC2</weapon>
|
||||
@ -283,8 +283,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>6400</health>
|
||||
<defense>50</defense>
|
||||
<health>85</health> <!-- 6400 -> 85 (scaled) -->
|
||||
<defense>5</defense> <!-- 50 -> 5 -->
|
||||
<moveSpeed>2</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterD1</weapon>
|
||||
@ -318,8 +318,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>7200</health>
|
||||
<defense>0</defense>
|
||||
<health>95</health> <!-- 7200 -> 95 (scaled) -->
|
||||
<defense>0</defense> <!-- 0 -> 0 (no change) -->
|
||||
<moveSpeed>3</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterD2</weapon>
|
||||
@ -353,8 +353,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>6550</health>
|
||||
<defense>240</defense>
|
||||
<health>90</health> <!-- 6550 -> 90 (scaled) -->
|
||||
<defense>24</defense> <!-- 240 -> 24 -->
|
||||
<moveSpeed>3</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterE1</weapon>
|
||||
@ -388,8 +388,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>9120</health>
|
||||
<defense>320</defense>
|
||||
<health>120</health> <!-- 9120 -> 120 (scaled) -->
|
||||
<defense>32</defense> <!-- 320 -> 32 -->
|
||||
<moveSpeed>3</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterE2</weapon>
|
||||
@ -423,8 +423,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>42000</health>
|
||||
<defense>770</defense>
|
||||
<health>420</health> <!-- 42000 -> 420 (scaled) -->
|
||||
<defense>70</defense> <!-- 770 -> 70 (scaled) -->
|
||||
<moveSpeed>2</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterF1</weapon>
|
||||
@ -458,8 +458,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>48000</health>
|
||||
<defense>560</defense>
|
||||
<health>480</health> <!-- 48000 -> 480 (scaled) -->
|
||||
<defense>50</defense> <!-- 560 -> 50 (scaled) -->
|
||||
<moveSpeed>2</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MonsterF2</weapon>
|
||||
@ -494,8 +494,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>4800</health>
|
||||
<defense>66</defense>
|
||||
<health>60</health> <!-- 4800 -> 60 (scaled) -->
|
||||
<defense>7</defense> <!-- 66 -> 7 (scaled) -->
|
||||
<moveSpeed>8</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MaskMonster</weapon>
|
||||
@ -529,8 +529,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>9600</health>
|
||||
<defense>132</defense>
|
||||
<health>120</health> <!-- 9600 -> 120 (scaled) -->
|
||||
<defense>13</defense> <!-- 132 -> 13 (scaled) -->
|
||||
<moveSpeed>8</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_MaskMonsterElite</weapon>
|
||||
@ -564,8 +564,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>6666</health>
|
||||
<defense>-66</defense>
|
||||
<health>90</health> <!-- 6666 -> 90 (scaled) -->
|
||||
<defense>-7</defense> <!-- -66 -> -7 (scaled) -->
|
||||
<moveSpeed>0</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_HologramMonster</weapon>
|
||||
@ -599,8 +599,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>16666</health>
|
||||
<defense>-166</defense>
|
||||
<health>200</health> <!-- 16666 -> 200 (scaled) -->
|
||||
<defense>-17</defense> <!-- -166 -> -17 (scaled) -->
|
||||
<moveSpeed>0</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_HologramMonsterElite</weapon>
|
||||
@ -634,8 +634,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>5630</health>
|
||||
<defense>78</defense>
|
||||
<health>75</health> <!-- 5630 -> 75 (scaled) -->
|
||||
<defense>8</defense> <!-- 78 -> 8 (scaled) -->
|
||||
<moveSpeed>2</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_SnakeMonster</weapon>
|
||||
@ -669,8 +669,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>11260</health>
|
||||
<defense>156</defense>
|
||||
<health>150</health> <!-- 11260 -> 150 (scaled) -->
|
||||
<defense>16</defense> <!-- 156 -> 16 (scaled) -->
|
||||
<moveSpeed>2</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_SnakeMonsterElite</weapon>
|
||||
@ -704,8 +704,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>111</health>
|
||||
<defense>1</defense>
|
||||
<health>3</health> <!-- 111 -> 3 (scaled) -->
|
||||
<defense>0</defense> <!-- 1 -> 0 (scaled) -->
|
||||
<moveSpeed>11</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_RatMonster</weapon>
|
||||
@ -739,8 +739,8 @@
|
||||
<behaviorTree>BasicMonsterBehavior</behaviorTree>
|
||||
<affiliation>monster</affiliation>
|
||||
<attributes>
|
||||
<health>222</health>
|
||||
<defense>2</defense>
|
||||
<health>5</health> <!-- 222 -> 5 (scaled) -->
|
||||
<defense>0</defense> <!-- 2 -> 0 (scaled) -->
|
||||
<moveSpeed>22</moveSpeed>
|
||||
</attributes>
|
||||
<weapon>Weapon_RatMonsterElite</weapon>
|
||||
|
Reference in New Issue
Block a user