因为在制作动作的时候,希望能看到一些特效的配合,实时表现,所以诞生了这篇文章。 因为编辑器原本并不支持在编辑模式下,预览执行,添加的ActionNode,所以我自己拓展了一下,以便于开发。 首先找到ActionConfigAttribute脚本,添加字段,用来标识,这个ActionNode会在编辑器下运行 然后在ActionMachineHelper脚本下对GetActionHandler进行修改,在寻找ActionNode时,标识是否只获取在编辑器下运行的Node 最后找到ActionEditorSetting,添加UpdateExecuteInEditorActionNode方法,添加在这里 代码我就不进行讲解了,自己看吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private void UpdateExecuteInEditorActionNode()
{
foreach (var item in currentState.actions)
{
int beginFrame = 0;
int endFrame = currentState.frames.Count;
var action = ActionMachineHelper.GetActionHandler(item.GetType(), true);
if (null != action)
{
if (item is IHoldFrames holdFrames)
{
beginFrame = holdFrames.GetBeginFrame();
endFrame = holdFrames.GetEndFrame();
}

ActionNode actionNode = ActionMachineHelper.CreateActionNode();
var actionMachineController = actionMachineTest.GetComponent<ActionMachineController>();
actionMachineController.actionMachine = new ActionMachine();
actionMachineController.actionMachine.controller = actionMachineController;
actionNode.actionMachine = actionMachineController.actionMachine;
actionNode.config = item;
actionNode.SetUpdateCnt(frameSelectIndex - beginFrame);
actionNode.handler = action;

if (frameSelectIndex >= beginFrame
&& frameSelectIndex <= endFrame)
{
if (beginFrame == frameSelectIndex)
{
actionNode.handler.Enter(actionNode);
}
actionNode.handler.Update(actionNode, setting.frameRate);
if (endFrame == frameSelectIndex)
{
actionNode.handler.Exit(actionNode);
}
}
}
}
}

最后应该会有一个报错,记得加个参数设置为false就好了

1
actionNode.handler = ActionMachineHelper.GetActionHandler(action.GetType(), false);

现在应该就能在编辑模式下,执行我们自己添加的Node了,需要注意,Node中的Data我没有进行保存,有需要就自己改把,所以如果有需要的话编辑器下的代码要做区分。 这里再顺手贴一个基于帧变化的粒子控制节点,和动画节点,因为贴图制作时会特效不会和动画绑定在一起,而且当攻速发生变化的时候,动画和粒子也需要统一进行缩放变化,报错的话,自己删了改成常量就行了,根据自己项目需求来。

粒子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using TFramework.ECS.MonoBehaviours;
using TFramework.Extensions;
using UnityEngine;
using XMLib.AM;

[System.Serializable]
[ActionConfig(typeof(ParticleSystemAction), true)]
public class ParticleSystemActionConfig : HoldFrames
{
public string ParticleName;
}

public class ParticleSystemAction : IActionHandler
{
public class Data
{
public ParticleSystem ParticleSystem;
public ActionMachineComponent ActionMachineComponent;
}

private ParticleSystem GetParticleSystem(ActionNode node)
{
ParticleSystem particleSystem;
Data data = node.data as Data;
if (null != data
&& null != data.ParticleSystem)
{
particleSystem = data.ParticleSystem;
}
else
{
ActionMachineController controller = (ActionMachineController)node.actionMachine.controller;
var config = node.config as ParticleSystemActionConfig;
particleSystem = controller.modelRoot.Find(config.ParticleName).GetComponent<ParticleSystem>();
if (null != data)
{
data.ParticleSystem = particleSystem;
}
}
return particleSystem;
}

private ActionMachineComponent GetActionMachineComponent(ActionNode node)
{
Data data = node.data as Data;
if (null != data
&& null != data.ActionMachineComponent)
{
return data.ActionMachineComponent;
}
else
{
ActionMachineController controller = (ActionMachineController)node.actionMachine.controller;
var entityView = controller.modelRoot.GetComponent<EntityView>();
if (null != entityView)
{
if (null != data)
{
data.ActionMachineComponent = entityView.Entity.GetComponent<ActionMachineComponent>();
return data.ActionMachineComponent;
}
}
return null;
}
}

public void Enter(ActionNode node)
{
Data data = new Data();
node.data = data;
var particleSystem = GetParticleSystem(node);
if (null != particleSystem)
{
var mainModule = particleSystem.main;
particleSystem.gameObject.SetActive(true);
particleSystem.Play();
particleSystem.Simulate(0, true, true);
particleSystem.time = 0;
var actionMachineComponent = GetActionMachineComponent(node);
mainModule.simulationSpeed = null == actionMachineComponent ? 1 : actionMachineComponent.Speed;
#if UNITY_EDITOR
UnityEditor.SceneView.RepaintAll();
#endif
}
}

public void Update(ActionNode node, float deltaTime)
{
var particleSystem = GetParticleSystem(node);
if (null != particleSystem)
{
var mainModule = particleSystem.main;
bool rest = particleSystem.time >= mainModule.startLifetime.constantMax ? true : false;
particleSystem.Simulate(deltaTime * node.updateCnt, true, rest);
var actionMachineComponent = GetActionMachineComponent(node);
mainModule.simulationSpeed = null == actionMachineComponent ? 1 : actionMachineComponent.Speed;
#if UNITY_EDITOR
UnityEditor.SceneView.RepaintAll();
#endif
}
}

public void Exit(ActionNode node)
{
var particleSystem = GetParticleSystem(node);
if (null != particleSystem)
{
var mainModule = particleSystem.main;
mainModule.simulationSpeed = 1;
particleSystem.Stop();
particleSystem.gameObject.SetActive(false);
#if UNITY_EDITOR
UnityEditor.SceneView.RepaintAll();
#endif
}
}
}

动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
using TFramework.ECS.MonoBehaviours;
using TFramework.Extensions;
using UnityEngine;
using XMLib.AM;

[System.Serializable]
[ActionConfig(typeof(EffectAnimatorAction), true)]
public class EffectAnimatorConfig : HoldFrames
{
public string PreafabName;
public string EffectName;
public Vector3 StartPosition;
}

public class EffectAnimatorAction : IActionHandler
{
public class Data
{
public Animator Animator;
public ActionMachineComponent ActionMachineComponent;
}

private Animator GetAnimatorController(ActionNode node)
{
Data data = node.data as Data;
if (null != data
&& null != data.Animator)
{
return data.Animator;
}
else
{
ActionMachineController controller = (ActionMachineController)node.actionMachine.controller;
var config = node.config as EffectAnimatorConfig;
var animator = controller.modelRoot.Find(config.PreafabName).GetComponent<Animator>();
if (null != data)
{
data.Animator = animator;
}
return animator;
}
}

private ActionMachineComponent GetActionMachineComponent(ActionNode node)
{
Data data = node.data as Data;
if (null != data
&& null != data.ActionMachineComponent)
{
return data.ActionMachineComponent;
}
else
{
ActionMachineController controller = (ActionMachineController)node.actionMachine.controller;
var entityView = controller.modelRoot.GetComponent<EntityView>();
if (null != entityView)
{
if (null != data)
{
data.ActionMachineComponent = entityView.Entity.GetComponent<ActionMachineComponent>();
return data.ActionMachineComponent;
}
}
return null;
}
}

public void Enter(ActionNode node)
{
Data data = new Data();
node.data = data;
var animator = GetAnimatorController(node);
if (null != animator)
{
var config = node.config as EffectAnimatorConfig;
animator.transform.localPosition = config.StartPosition;
animator.gameObject.SetActive(true);
var actionMachineComponent = GetActionMachineComponent(node);
animator.speed = null == actionMachineComponent ? 1 : actionMachineComponent.Speed;
animator.Play(config.EffectName, 0, 0);
#if UNITY_EDITOR
UnityEditor.SceneView.RepaintAll();
#endif
}
}

public void Update(ActionNode node, float deltaTime)
{
var animator = GetAnimatorController(node);
if (null != animator)
{
var actionMachineComponent = GetActionMachineComponent(node);
animator.speed = null == actionMachineComponent ? 1 : actionMachineComponent.Speed;
if (Application.isPlaying)
{
animator.Update(deltaTime);
}
else
{
float time = deltaTime * node.updateCnt;
var config = node.config as EffectAnimatorConfig;
GetCurrentAnimationClip(animator, config.EffectName).SampleAnimation(animator.gameObject, time);
}
#if UNITY_EDITOR
UnityEditor.SceneView.RepaintAll();
#endif
}
}

public AnimationClip GetCurrentAnimationClip(Animator animator, string state)
{
return Array.Find(animator.runtimeAnimatorController.animationClips, t => string.Compare(state, t.name) == 0);
}

public void Exit(ActionNode node)
{
var animator = GetAnimatorController(node);
if (null != animator)
{
animator.speed = 1;
animator.gameObject.SetActive(false);
#if UNITY_EDITOR
UnityEditor.SceneView.RepaintAll();
#endif
}
}
}

最后贴一下编辑器地址