[Mini-Mechanisms#1] State-Driven Camera Motion
== Intro ==
- use case: 假设一个棋牌游戏的房间,玩家进入房间后处于站立视角,点击座位后,玩家入座,视角切换,开始游戏
- Mechanism: State-Driven Camera Motion
== Problems ==
[1] Locate UI
- 将UI部件根据世界坐标下物件放置到屏幕上对应位置
[2] Smooth Camera Motion
- 需要进行平滑的相机移动
- 总共有四种视角:Stand Up视角 * 1, Sit Down视角 * 3。
- 根据玩家选择的不同,镜头移动到不同的Sit Down视角
- 点击Stand Up Btn 后,回到Stand Up视角
== Solutions ==
[1] Locate UI
- 使用Camera.WorldToScreenPoint
- https://docs.unity3d.com/ScriptReference/Camera.WorldToScreenPoint.html
- 为Take Seat Btn添加一个Component
- 为该Component指出跟随目标的Transform
- Btn UI在Update中不断Locate(),移动到对应屏幕位置
[2] Smooth Camera Motion
- 使用Unity 提供的Cinemachine
- #1 使用Virtual Camera搭配Dolly Track
- https://www.youtube.com/watch?v=q1fkx94vHtg&list=PLX2vGYjWbI0TQpl4JdfEDNO1xK_I34y8P&index=2
- 设置一个Fellow Target Transform(代表Player),在Player移动时,Camera在指定的Dolly Track上跟随Player移动
- 效果不太理想,实现略复杂。原因在于本例的重点不在跟随,需要关注的是State Change(Stand up、Sit Down 0/1/2)
- #2 使用State-Driven Cameras
- 设置Player Animator和State(Stand up、Sit Down 0/1/2),状态迁移可以简单的通过Seat Id equals xxx来实现(Stand up处seat id = -1)
- 为对应的State创建对应的camera
- #1 使用Virtual Camera搭配Dolly Track
== Locate UI ==
[1] ScreenPosLocator
using UnityEngine; namespace CameraMotion.Scripts { public class ScreenPosLocator : MonoBehaviour { public Transform followTransform; public Vector3 offset; public bool shouldFellow; private Camera camera; public void Awake() { camera = Camera.main; } public void Update() { Locate(); } private void Locate() { if (shouldFellow) { transform.position = camera.WorldToScreenPoint(followTransform.position + offset); } } } }
[2] Seat
using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; namespace CameraMotion.Scripts { public class Seat : MonoBehaviour { public int seatId; public Button btnTakeSeat; public UnityEvent<Seat> playerSitDownEvent; private bool available; public void Awake() { available = true; btnTakeSeat.onClick.AddListener(OnOccupied); } public void Occupy() { available = false; } public void Release() { available = true; } public void Disable() { btnTakeSeat.gameObject.SetActive(false); } public void TryEnable() { if (available) { Enable(); } } private void Enable() { btnTakeSeat.gameObject.SetActive(true); } private void OnOccupied() { playerSitDownEvent?.Invoke(this); } } }
[3] 在Editor中配置
== State-Driven Camera Motion ==
[1] 添加Cinemachine
-
add a Cinemachine Brian component to your Main Camera
-
-
add a vcam(main): Object>Cinemachine>Virtual Camera
-
[2] 主视角
- 将Look At设置为桌面(Table Transform)
- 对Main Camera的Transform进行调整,获得我们想要的主视角
[2]玩家视角
-
add State-Driven Camera: GameObject>Cinemachine>State-Driven Camera
- 复制粘贴复制粘贴,注意需要的使用的vcam必须是CM StateDrivenCamera的Child
-
将各个Seat vcam的 Look At 均设置为Table
[3] 视角变换
- 创建一个新的GameObject - Player,并为它创建一个Animator
-
为Player State Animator设置 States 和 Transitions, Take Seat 0/1/2分别代表玩家选中了该处座位
-
调整Transform 和 Ortho Size找到Player Sit Down视角
-
将Animated Target设置为 Player Animator
-
填入State和对应的Camera















浙公网安备 33010602011771号