|
前言
美术地编在编辑场景的时候,需要边跑场景边修改场景物件。一般跑场景工具是在运行时启动,但是运行时编辑场景物件一般是没法保存的,所以有了这个工具的需求。这个工具可以在非运行时跑角色,因为在非运行时,所以可以边跑场景,边编辑场景物件。
https://www.zhihu.com/video/1609530758191616000
实现
非运行时的角色动画处理
unity的动画支持在非运行状态播放动画,首先使用StartAnimationMode函数启动动画
AnimationMode.StartAnimationMode();
文档 : AnimationMode.StartAnimationMode
然后使用SampleAnimationClip播放指定的片段,这样就能在非运行时播放动画
AnimationMode.SampleAnimationClip(m_Anim.gameObject, m_IdleClip, m_AnimPlayTime);
文档 :AnimationMode.SampleAnimationClip
SceneView中的摄像机处理
SceneView可以控制参数的变量是pivot和rotation,顾名思义,pivot是设置的摄像机的中心点,rotation是设置的摄像机的旋转。
Unity - Scripting API: SceneView.pivot
SceneView.rotation
Demo中pivot设置角色的位置 + 偏移,rotation设置为摄像机当前的旋转量
// 场景视图的旋转和中心点
Quaternion animRotation = Quaternion.Euler(-m_AngleV, m_AngleH, 0.0f);
m_SceneView.rotation = animRotation;
m_SceneView.pivot = m_Player.position + lookatPosOffset;
那么如何控制摄像机的远近距离在一个范围内,可以通过控制SceneView.size来近似的模拟这个范围。通过源码获知,SceneView.size值的大小可以影响camDistance的大小
Unity - Scripting API: SceneView.size
// 模拟设置摄像机距离的最小最大值
m_SceneView.size = Mathf.Clamp(m_SceneView.size, camDisRange.x, camDisRange.y);
通过设置了pivot,rotation和size参数,SceneView类内部会根据这些变量计算摄像机的Transform, 伪代码如下
camera.rotation = SceneView.rotation;
camera.position = SceneView.pivit + SceneView.rotation * new Vector3(0, 0, -cameraDistance);
输入事件的逻辑控制
通过监听SceneView.duringSceneGui的回调可以得到键盘输入和鼠标输入事件,这里主要讲下键盘事件的处理
首先注册WADS的键盘事件
m_DirKeyBindings.Clear();
m_DirKeyBindings.Add(KeyCode.W, WalkForward);
m_DirKeyBindings.Add(KeyCode.S, WalkBackward);
m_DirKeyBindings.Add(KeyCode.A, WalkLeft);
m_DirKeyBindings.Add(KeyCode.D, WalkRight);
看下某个键盘事件的函数,当按下按键的时候,会赋值,当松开按键的时候,值清0
void WalkForward(ShortcutStage stage)
{
m_CurrentInputVector.y =
(stage == ShortcutStage.Begin) ? 0.5f : ((m_CurrentInputVector.y > 0f) ? 0f : m_CurrentInputVector.y);
if (m_SceneView != null)
{
m_SceneView.Repaint();
}
}
当按住多个按键的时候,比如按住了WA按键,会往斜方向跑,这时候松开一个按键,只会把一个移动值设置为0,只有当所有的按键都放开的时候,才会停止运动。这样才能达到平滑的运动的效果。
case EventType.KeyDown:
{
KeyCode keyCode = evt.keyCode;
if (m_DirKeyBindings.TryGetValue(keyCode, out action))
{
action(ShortcutStage.Begin);
m_Anim.Run();
m_Move.SetMoveParam(m_CurrentInputVector.x, m_CurrentInputVector.y, isSpeedUp);
m_DirKeysDown.Add(keyCode);
evt.Use();
}
}
break;
case EventType.KeyUp:
{
KeyCode keyCode = evt.keyCode;
if (m_DirKeyBindings.TryGetValue(keyCode, out action))
{
action(ShortcutStage.End);
m_Move.SetMoveParam(m_CurrentInputVector.x, m_CurrentInputVector.y, isSpeedUp);
m_DirKeysDown.Remove(keyCode);
if (m_DirKeysDown.Count == 0)
{
m_CurrentInputVector = Vector3.zero;
m_Anim.Idle();
m_Move.SetMoveParam(0, 0, false);
}
evt.Use();
}
}
break;
其他问题
在OnDrawGizmos函数刷新SceneView界面
private void OnDrawGizmos()
{
EditorApplication.QueuePlayerLoopUpdate();
}
这时候转动镜头,镜头会晃动,如下图所示
https://www.zhihu.com/video/1609543320451198976
正确做法是监听EditorApplication.update事件,在里面刷新SceneView
EditorApplication.update += OnEditorAppUpdate;
void OnEditorAppUpdate()
{
EditorApplication.QueuePlayerLoopUpdate();
//SceneView.RepaintAll();
}
项目地址
GitHub - xieliujian/UnityDemo_ScenePlayerRoam: Unity非运行时角色跑场景
参考文章
Unity非运行模式下实现动画播放/回退工具 - chiguozi - 博客园
Unity3D研究院之同步Scene与Game视图摄像机 | 雨松MOMO程序研究院
UnityCsReference/CameraFlyModeContext.cs at master · Unity-Technologies/UnityCsReference
Unity在Editor下获取键盘等设备Input事件 - 小宝笔记
UnityCsReference/SceneView.cs at master · Unity-Technologies/UnityCsReference |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|