CinemachineVirtualCamera.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. using Cinemachine.Utility;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.Serialization;
  6. namespace Cinemachine
  7. {
  8. /// <summary>
  9. /// This behaviour is intended to be attached to an empty Transform GameObject,
  10. /// and it represents a Virtual Camera within the Unity scene.
  11. ///
  12. /// The Virtual Camera will animate its Transform according to the rules contained
  13. /// in its CinemachineComponent pipeline (Aim, Body, and Noise). When the virtual
  14. /// camera is Live, the Unity camera will assume the position and orientation
  15. /// of the virtual camera.
  16. ///
  17. /// A virtual camera is not a camera. Instead, it can be thought of as a camera controller,
  18. /// not unlike a cameraman. It can drive the Unity Camera and control its position,
  19. /// orientation, lens settings, and PostProcessing effects. Each Virtual Camera owns
  20. /// its own Cinemachine Component Pipeline, through which you provide the instructions
  21. /// for dynamically tracking specific game objects.
  22. ///
  23. /// A virtual camera is very lightweight, and does no rendering of its own. It merely
  24. /// tracks interesting GameObjects, and positions itself accordingly. A typical game
  25. /// can have dozens of virtual cameras, each set up to follow a particular character
  26. /// or capture a particular event.
  27. ///
  28. /// A Virtual Camera can be in any of three states:
  29. ///
  30. /// * **Live**: The virtual camera is actively controlling the Unity Camera. The
  31. /// virtual camera is tracking its targets and being updated every frame.
  32. /// * **Standby**: The virtual camera is tracking its targets and being updated
  33. /// every frame, but no Unity Camera is actively being controlled by it. This is
  34. /// the state of a virtual camera that is enabled in the scene but perhaps at a
  35. /// lower priority than the Live virtual camera.
  36. /// * **Disabled**: The virtual camera is present but disabled in the scene. It is
  37. /// not actively tracking its targets and so consumes no processing power. However,
  38. /// the virtual camera can be made live from the Timeline.
  39. ///
  40. /// The Unity Camera can be driven by any virtual camera in the scene. The game
  41. /// logic can choose the virtual camera to make live by manipulating the virtual
  42. /// cameras' enabled flags and their priorities, based on game logic.
  43. ///
  44. /// In order to be driven by a virtual camera, the Unity Camera must have a CinemachineBrain
  45. /// behaviour, which will select the most eligible virtual camera based on its priority
  46. /// or on other criteria, and will manage blending.
  47. /// </summary>
  48. /// <seealso cref="CinemachineVirtualCameraBase"/>
  49. /// <seealso cref="LensSettings"/>
  50. /// <seealso cref="CinemachineComposer"/>
  51. /// <seealso cref="CinemachineTransposer"/>
  52. /// <seealso cref="CinemachineBasicMultiChannelPerlin"/>
  53. [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
  54. [DisallowMultipleComponent]
  55. [ExecuteAlways]
  56. [ExcludeFromPreset]
  57. [AddComponentMenu("Cinemachine/CinemachineVirtualCamera")]
  58. [HelpURL(Documentation.BaseURL + "manual/CinemachineVirtualCamera.html")]
  59. public class CinemachineVirtualCamera : CinemachineVirtualCameraBase
  60. {
  61. /// <summary>The object that the camera wants to look at (the Aim target).
  62. /// The Aim component of the CinemachineComponent pipeline
  63. /// will refer to this target and orient the vcam in accordance with rules and
  64. /// settings that are provided to it.
  65. /// If this is null, then the vcam's Transform orientation will be used.</summary>
  66. [Tooltip("The object that the camera wants to look at (the Aim target). "
  67. + "If this is null, then the vcam's Transform orientation will define the camera's orientation.")]
  68. [NoSaveDuringPlay]
  69. [VcamTargetProperty]
  70. public Transform m_LookAt = null;
  71. /// <summary>The object that the camera wants to move with (the Body target).
  72. /// The Body component of the CinemachineComponent pipeline
  73. /// will refer to this target and position the vcam in accordance with rules and
  74. /// settings that are provided to it.
  75. /// If this is null, then the vcam's Transform position will be used.</summary>
  76. [Tooltip("The object that the camera wants to move with (the Body target). "
  77. + "If this is null, then the vcam's Transform position will define the camera's position.")]
  78. [NoSaveDuringPlay]
  79. [VcamTargetProperty]
  80. public Transform m_Follow = null;
  81. /// <summary>Specifies the LensSettings of this Virtual Camera.
  82. /// These settings will be transferred to the Unity camera when the vcam is live.</summary>
  83. [FormerlySerializedAs("m_LensAttributes")]
  84. [Tooltip("Specifies the lens properties of this Virtual Camera. This generally "
  85. + "mirrors the Unity Camera's lens settings, and will be used to drive the "
  86. + "Unity camera when the vcam is active.")]
  87. public LensSettings m_Lens = LensSettings.Default;
  88. /// <summary> Collection of parameters that influence how this virtual camera transitions from
  89. /// other virtual cameras </summary>
  90. public TransitionParams m_Transitions;
  91. /// <summary>Legacy support</summary>
  92. [SerializeField] [HideInInspector]
  93. [FormerlySerializedAs("m_BlendHint")]
  94. [FormerlySerializedAs("m_PositionBlending")] private BlendHint m_LegacyBlendHint;
  95. /// <summary>This is the name of the hidden GameObject that will be created as a child object
  96. /// of the virtual camera. This hidden game object acts as a container for the polymorphic
  97. /// CinemachineComponent pipeline. The Inspector UI for the Virtual Camera
  98. /// provides access to this pipleline, as do the CinemachineComponent-family of
  99. /// public methods in this class.
  100. /// The lifecycle of the pipeline GameObject is managed automatically.</summary>
  101. public const string PipelineName = "cm";
  102. /// <summary>The CameraState object holds all of the information
  103. /// necessary to position the Unity camera. It is the output of this class.</summary>
  104. override public CameraState State { get { return m_State; } }
  105. /// <summary>Get the LookAt target for the Aim component in the Cinemachine pipeline.
  106. /// If this vcam is a part of a meta-camera collection, then the owner's target
  107. /// will be used if the local target is null.</summary>
  108. override public Transform LookAt
  109. {
  110. get { return ResolveLookAt(m_LookAt); }
  111. set { m_LookAt = value; }
  112. }
  113. /// <summary>Get the Follow target for the Body component in the Cinemachine pipeline.
  114. /// If this vcam is a part of a meta-camera collection, then the owner's target
  115. /// will be used if the local target is null.</summary>
  116. override public Transform Follow
  117. {
  118. get { return ResolveFollow(m_Follow); }
  119. set { m_Follow = value; }
  120. }
  121. /// <summary>
  122. /// Query components and extensions for the maximum damping time.
  123. /// </summary>
  124. /// <returns>Highest damping setting in this vcam</returns>
  125. public override float GetMaxDampTime()
  126. {
  127. float maxDamp = base.GetMaxDampTime();
  128. UpdateComponentPipeline();
  129. if (m_ComponentPipeline != null)
  130. for (int i = 0; i < m_ComponentPipeline.Length; ++i)
  131. maxDamp = Mathf.Max(maxDamp, m_ComponentPipeline[i].GetMaxDampTime());
  132. return maxDamp;
  133. }
  134. /// <summary>Internal use only. Do not call this method.
  135. /// Called by CinemachineCore at the appropriate Update time
  136. /// so the vcam can position itself and track its targets. This class will
  137. /// invoke its pipeline and generate a CameraState for this frame.</summary>
  138. /// <param name="worldUp">Effective world up</param>
  139. /// <param name="deltaTime">Effective deltaTime</param>
  140. override public void InternalUpdateCameraState(Vector3 worldUp, float deltaTime)
  141. {
  142. UpdateTargetCache();
  143. // Update the state by invoking the component pipeline
  144. m_State = CalculateNewState(worldUp, deltaTime);
  145. ApplyPositionBlendMethod(ref m_State, m_Transitions.m_BlendHint);
  146. // Push the raw position back to the game object's transform, so it
  147. // moves along with the camera.
  148. var pos = transform.position;
  149. var rot = transform.rotation;
  150. if (Follow != null)
  151. pos = m_State.RawPosition;
  152. if (LookAt != null)
  153. rot = m_State.RawOrientation;
  154. transform.ConservativeSetPositionAndRotation(pos, rot);
  155. PreviousStateIsValid = true;
  156. }
  157. /// <summary>Make sure that the pipeline cache is up-to-date.</summary>
  158. override protected void OnEnable()
  159. {
  160. base.OnEnable();
  161. m_State = PullStateFromVirtualCamera(Vector3.up, ref m_Lens);
  162. InvalidateComponentPipeline();
  163. // Can't add components during OnValidate
  164. if (ValidatingStreamVersion < 20170927)
  165. {
  166. if (Follow != null && GetCinemachineComponent(CinemachineCore.Stage.Body) == null)
  167. AddCinemachineComponent<CinemachineHardLockToTarget>();
  168. if (LookAt != null && GetCinemachineComponent(CinemachineCore.Stage.Aim) == null)
  169. AddCinemachineComponent<CinemachineHardLookAt>();
  170. }
  171. }
  172. /// <summary>Calls the DestroyPipelineDelegate for destroying the hidden
  173. /// child object, to support undo.</summary>
  174. protected override void OnDestroy()
  175. {
  176. // Make the pipeline visible instead of destroying - this is to keep Undo happy
  177. foreach (Transform child in transform)
  178. if (child.GetComponent<CinemachinePipeline>() != null)
  179. child.gameObject.hideFlags
  180. &= ~(HideFlags.HideInHierarchy | HideFlags.HideInInspector);
  181. base.OnDestroy();
  182. }
  183. /// <summary>Enforce bounds for fields, when changed in inspector.</summary>
  184. protected override void OnValidate()
  185. {
  186. base.OnValidate();
  187. m_Lens.Validate();
  188. if (m_LegacyBlendHint != BlendHint.None)
  189. {
  190. m_Transitions.m_BlendHint = m_LegacyBlendHint;
  191. m_LegacyBlendHint = BlendHint.None;
  192. }
  193. }
  194. void OnTransformChildrenChanged()
  195. {
  196. InvalidateComponentPipeline();
  197. }
  198. void Reset()
  199. {
  200. DestroyPipeline();
  201. UpdateComponentPipeline();
  202. }
  203. /// <summary>
  204. /// Override component pipeline creation.
  205. /// This needs to be done by the editor to support Undo.
  206. /// The override must do exactly the same thing as the CreatePipeline method in this class.
  207. /// </summary>
  208. public static CreatePipelineDelegate CreatePipelineOverride;
  209. /// <summary>
  210. /// Override component pipeline creation.
  211. /// This needs to be done by the editor to support Undo.
  212. /// The override must do exactly the same thing as the CreatePipeline method in
  213. /// the CinemachineVirtualCamera class.
  214. /// </summary>
  215. public delegate Transform CreatePipelineDelegate(
  216. CinemachineVirtualCamera vcam, string name, CinemachineComponentBase[] copyFrom);
  217. /// <summary>
  218. /// Override component pipeline destruction.
  219. /// This needs to be done by the editor to support Undo.
  220. /// </summary>
  221. public static DestroyPipelineDelegate DestroyPipelineOverride;
  222. /// <summary>
  223. /// Override component pipeline destruction.
  224. /// This needs to be done by the editor to support Undo.
  225. /// </summary>
  226. public delegate void DestroyPipelineDelegate(GameObject pipeline);
  227. /// <summary>Destroy any existing pipeline container.</summary>
  228. internal void DestroyPipeline()
  229. {
  230. List<Transform> oldPipeline = new List<Transform>();
  231. foreach (Transform child in transform)
  232. if (child.GetComponent<CinemachinePipeline>() != null)
  233. oldPipeline.Add(child);
  234. foreach (Transform child in oldPipeline)
  235. {
  236. if (DestroyPipelineOverride != null)
  237. DestroyPipelineOverride(child.gameObject);
  238. else
  239. {
  240. var oldStuff = child.GetComponents<CinemachineComponentBase>();
  241. foreach (var c in oldStuff)
  242. Destroy(c);
  243. if (!RuntimeUtility.IsPrefab(gameObject))
  244. Destroy(child.gameObject);
  245. }
  246. }
  247. m_ComponentOwner = null;
  248. InvalidateComponentPipeline();
  249. PreviousStateIsValid = false;
  250. }
  251. /// <summary>Create a default pipeline container.
  252. /// Note: copyFrom only supported in Editor, not build</summary>
  253. internal Transform CreatePipeline(CinemachineVirtualCamera copyFrom)
  254. {
  255. CinemachineComponentBase[] components = null;
  256. if (copyFrom != null)
  257. {
  258. copyFrom.InvalidateComponentPipeline(); // make sure it's up to date
  259. components = copyFrom.GetComponentPipeline();
  260. }
  261. Transform newPipeline = null;
  262. if (CreatePipelineOverride != null)
  263. newPipeline = CreatePipelineOverride(this, PipelineName, components);
  264. else if (!RuntimeUtility.IsPrefab(gameObject))
  265. {
  266. GameObject go = new GameObject(PipelineName);
  267. go.transform.parent = transform;
  268. go.AddComponent<CinemachinePipeline>();
  269. newPipeline = go.transform;
  270. }
  271. PreviousStateIsValid = false;
  272. return newPipeline;
  273. }
  274. /// <summary>
  275. /// Editor API: Call this when changing the pipeline from the editor.
  276. /// Will force a rebuild of the pipeline cache.
  277. /// </summary>
  278. public void InvalidateComponentPipeline() { m_ComponentPipeline = null; }
  279. /// <summary>Get the hidden CinemachinePipeline child object.</summary>
  280. /// <returns>The hidden CinemachinePipeline child object</returns>
  281. public Transform GetComponentOwner() { UpdateComponentPipeline(); return m_ComponentOwner; }
  282. /// <summary>Get the component pipeline owned by the hidden child pipline container.
  283. /// For most purposes, it is preferable to use the GetCinemachineComponent method.</summary>
  284. /// <returns>The component pipeline</returns>
  285. public CinemachineComponentBase[] GetComponentPipeline() { UpdateComponentPipeline(); return m_ComponentPipeline; }
  286. /// <summary>Get the component set for a specific stage.</summary>
  287. /// <param name="stage">The stage for which we want the component</param>
  288. /// <returns>The Cinemachine component for that stage, or null if not defined</returns>
  289. public CinemachineComponentBase GetCinemachineComponent(CinemachineCore.Stage stage)
  290. {
  291. CinemachineComponentBase[] components = GetComponentPipeline();
  292. if (components != null)
  293. foreach (var c in components)
  294. if (c.Stage == stage)
  295. return c;
  296. return null;
  297. }
  298. /// <summary>Get an existing component of a specific type from the cinemachine pipeline.</summary>
  299. /// <typeparam name="T">The type of component to get</typeparam>
  300. /// <returns>The component if it's present, or null</returns>
  301. public T GetCinemachineComponent<T>() where T : CinemachineComponentBase
  302. {
  303. CinemachineComponentBase[] components = GetComponentPipeline();
  304. if (components != null)
  305. foreach (var c in components)
  306. if (c is T)
  307. return c as T;
  308. return null;
  309. }
  310. /// <summary>Add a component to the cinemachine pipeline.
  311. /// Existing components at the new component's stage are removed</summary>
  312. /// <typeparam name="T">The type of component to add</typeparam>
  313. /// <returns>The new component</returns>
  314. public T AddCinemachineComponent<T>() where T : CinemachineComponentBase
  315. {
  316. // Get the existing components
  317. Transform owner = GetComponentOwner();
  318. if (owner == null)
  319. return null; // maybe it's a prefab
  320. CinemachineComponentBase[] components = owner.GetComponents<CinemachineComponentBase>();
  321. T component = owner.gameObject.AddComponent<T>();
  322. if (component != null && components != null)
  323. {
  324. // Remove the existing components at that stage
  325. CinemachineCore.Stage stage = component.Stage;
  326. for (int i = components.Length - 1; i >= 0; --i)
  327. {
  328. if (components[i].Stage == stage)
  329. {
  330. components[i].enabled = false;
  331. RuntimeUtility.DestroyObject(components[i]);
  332. }
  333. }
  334. }
  335. InvalidateComponentPipeline();
  336. return component;
  337. }
  338. /// <summary>Remove a component from the cinemachine pipeline if it's present.</summary>
  339. /// <typeparam name="T">The type of component to remove</typeparam>
  340. public void DestroyCinemachineComponent<T>() where T : CinemachineComponentBase
  341. {
  342. CinemachineComponentBase[] components = GetComponentPipeline();
  343. if (components != null)
  344. {
  345. foreach (var c in components)
  346. {
  347. if (c is T)
  348. {
  349. c.enabled = false;
  350. RuntimeUtility.DestroyObject(c);
  351. InvalidateComponentPipeline();
  352. }
  353. }
  354. }
  355. }
  356. CameraState m_State = CameraState.Default; // Current state this frame
  357. CinemachineComponentBase[] m_ComponentPipeline = null;
  358. // Serialized only to implement copy/paste of CM subcomponents.
  359. // Note however that this strategy has its limitations: the CM pipeline Components
  360. // won't be pasted onto a prefab asset outside the scene unless the prefab
  361. // is opened in Prefab edit mode.
  362. [SerializeField][HideInInspector] private Transform m_ComponentOwner = null;
  363. void UpdateComponentPipeline()
  364. {
  365. #if UNITY_EDITOR
  366. // Did we just get copy/pasted?
  367. if (m_ComponentOwner != null && m_ComponentOwner.parent != transform)
  368. {
  369. CinemachineVirtualCamera copyFrom = (m_ComponentOwner.parent != null)
  370. ? m_ComponentOwner.parent.gameObject.GetComponent<CinemachineVirtualCamera>() : null;
  371. DestroyPipeline();
  372. CreatePipeline(copyFrom);
  373. m_ComponentOwner = null;
  374. }
  375. // Make sure the pipeline stays hidden, even through prefab
  376. if (m_ComponentOwner != null)
  377. SetFlagsForHiddenChild(m_ComponentOwner.gameObject);
  378. #endif
  379. // Early out if we're up-to-date
  380. if (m_ComponentOwner != null && m_ComponentPipeline != null)
  381. return;
  382. m_ComponentOwner = null;
  383. List<CinemachineComponentBase> list = new List<CinemachineComponentBase>();
  384. foreach (Transform child in transform)
  385. {
  386. if (child.GetComponent<CinemachinePipeline>() != null)
  387. {
  388. CinemachineComponentBase[] components = child.GetComponents<CinemachineComponentBase>();
  389. foreach (CinemachineComponentBase c in components)
  390. if (c.enabled)
  391. list.Add(c);
  392. m_ComponentOwner = child;
  393. break;
  394. }
  395. }
  396. // Make sure we have a pipeline owner
  397. if (m_ComponentOwner == null)
  398. m_ComponentOwner = CreatePipeline(null);
  399. if (m_ComponentOwner != null && m_ComponentOwner.gameObject != null)
  400. {
  401. // Sort the pipeline
  402. list.Sort((c1, c2) => (int)c1.Stage - (int)c2.Stage);
  403. m_ComponentPipeline = list.ToArray();
  404. }
  405. }
  406. static internal void SetFlagsForHiddenChild(GameObject child)
  407. {
  408. if (child != null)
  409. {
  410. if (CinemachineCore.sShowHiddenObjects)
  411. child.hideFlags &= ~(HideFlags.HideInHierarchy | HideFlags.HideInInspector);
  412. else
  413. child.hideFlags |= (HideFlags.HideInHierarchy | HideFlags.HideInInspector);
  414. }
  415. }
  416. private Transform mCachedLookAtTarget;
  417. private CinemachineVirtualCameraBase mCachedLookAtTargetVcam;
  418. private CameraState CalculateNewState(Vector3 worldUp, float deltaTime)
  419. {
  420. FollowTargetAttachment = 1;
  421. LookAtTargetAttachment = 1;
  422. // Initialize the camera state, in case the game object got moved in the editor
  423. CameraState state = PullStateFromVirtualCamera(worldUp, ref m_Lens);
  424. Transform lookAtTarget = LookAt;
  425. if (lookAtTarget != mCachedLookAtTarget)
  426. {
  427. mCachedLookAtTarget = lookAtTarget;
  428. mCachedLookAtTargetVcam = null;
  429. if (lookAtTarget != null)
  430. mCachedLookAtTargetVcam = lookAtTarget.GetComponent<CinemachineVirtualCameraBase>();
  431. }
  432. if (lookAtTarget != null)
  433. {
  434. if (mCachedLookAtTargetVcam != null)
  435. state.ReferenceLookAt = mCachedLookAtTargetVcam.State.FinalPosition;
  436. else
  437. state.ReferenceLookAt = TargetPositionCache.GetTargetPosition(lookAtTarget);
  438. }
  439. // Update the state by invoking the component pipeline
  440. UpdateComponentPipeline(); // avoid GetComponentPipeline() here because of GC
  441. // Extensions first
  442. InvokePrePipelineMutateCameraStateCallback(this, ref state, deltaTime);
  443. // Then components
  444. bool haveAim = false;
  445. if (m_ComponentPipeline == null)
  446. {
  447. for (var stage = CinemachineCore.Stage.Body; stage <= CinemachineCore.Stage.Finalize; ++stage)
  448. InvokePostPipelineStageCallback(this, stage, ref state, deltaTime);
  449. }
  450. else
  451. {
  452. for (int i = 0; i < m_ComponentPipeline.Length; ++i)
  453. if (m_ComponentPipeline[i] != null)
  454. m_ComponentPipeline[i].PrePipelineMutateCameraState(ref state, deltaTime);
  455. int componentIndex = 0;
  456. CinemachineComponentBase postAimBody = null;
  457. for (var stage = CinemachineCore.Stage.Body; stage <= CinemachineCore.Stage.Finalize; ++stage)
  458. {
  459. var c = componentIndex < m_ComponentPipeline.Length
  460. ? m_ComponentPipeline[componentIndex] : null;
  461. if (c != null && stage == c.Stage)
  462. {
  463. ++componentIndex;
  464. if (stage == CinemachineCore.Stage.Body && c.BodyAppliesAfterAim)
  465. {
  466. postAimBody = c;
  467. continue; // do the body stage of the pipeline after Aim
  468. }
  469. c.MutateCameraState(ref state, deltaTime);
  470. haveAim = stage == CinemachineCore.Stage.Aim;
  471. }
  472. InvokePostPipelineStageCallback(this, stage, ref state, deltaTime);
  473. // If we have saved a Body for after Aim, do it now
  474. if (stage == CinemachineCore.Stage.Aim && postAimBody != null)
  475. {
  476. postAimBody.MutateCameraState(ref state, deltaTime);
  477. InvokePostPipelineStageCallback(this, CinemachineCore.Stage.Body, ref state, deltaTime);
  478. }
  479. }
  480. }
  481. if (!haveAim)
  482. state.BlendHint |= CameraState.BlendHintValue.IgnoreLookAtTarget;
  483. return state;
  484. }
  485. /// <summary>This is called to notify the vcam that a target got warped,
  486. /// so that the vcam can update its internal state to make the camera
  487. /// also warp seamlessy.</summary>
  488. /// <param name="target">The object that was warped</param>
  489. /// <param name="positionDelta">The amount the target's position changed</param>
  490. public override void OnTargetObjectWarped(Transform target, Vector3 positionDelta)
  491. {
  492. if (target == Follow)
  493. {
  494. transform.position += positionDelta;
  495. m_State.RawPosition += positionDelta;
  496. }
  497. UpdateComponentPipeline(); // avoid GetComponentPipeline() here because of GC
  498. if (m_ComponentPipeline != null)
  499. {
  500. for (int i = 0; i < m_ComponentPipeline.Length; ++i)
  501. m_ComponentPipeline[i].OnTargetObjectWarped(target, positionDelta);
  502. }
  503. base.OnTargetObjectWarped(target, positionDelta);
  504. }
  505. /// <summary>
  506. /// Force the virtual camera to assume a given position and orientation
  507. /// </summary>
  508. /// <param name="pos">Worldspace pposition to take</param>
  509. /// <param name="rot">Worldspace orientation to take</param>
  510. public override void ForceCameraPosition(Vector3 pos, Quaternion rot)
  511. {
  512. PreviousStateIsValid = true;
  513. transform.ConservativeSetPositionAndRotation(pos, rot);
  514. m_State.RawPosition = pos;
  515. m_State.RawOrientation = rot;
  516. UpdateComponentPipeline(); // avoid GetComponentPipeline() here because of GC
  517. if (m_ComponentPipeline != null)
  518. for (int i = 0; i < m_ComponentPipeline.Length; ++i)
  519. m_ComponentPipeline[i].ForceCameraPosition(pos, rot);
  520. base.ForceCameraPosition(pos, rot);
  521. }
  522. // This is a hack for FreeLook rigs - to be removed
  523. internal void SetStateRawPosition(Vector3 pos) { m_State.RawPosition = pos; }
  524. /// <summary>If we are transitioning from another vcam, grab the position from it.</summary>
  525. /// <param name="fromCam">The camera being deactivated. May be null.</param>
  526. /// <param name="worldUp">Default world Up, set by the CinemachineBrain</param>
  527. /// <param name="deltaTime">Delta time for time-based effects (ignore if less than or equal to 0)</param>
  528. public override void OnTransitionFromCamera(
  529. ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime)
  530. {
  531. base.OnTransitionFromCamera(fromCam, worldUp, deltaTime);
  532. InvokeOnTransitionInExtensions(fromCam, worldUp, deltaTime);
  533. bool forceUpdate = false;
  534. if (m_Transitions.m_InheritPosition && fromCam != null
  535. && !CinemachineCore.Instance.IsLiveInBlend(this))
  536. ForceCameraPosition(fromCam.State.FinalPosition, fromCam.State.FinalOrientation);
  537. UpdateComponentPipeline(); // avoid GetComponentPipeline() here because of GC
  538. if (m_ComponentPipeline != null)
  539. {
  540. for (int i = 0; i < m_ComponentPipeline.Length; ++i)
  541. if (m_ComponentPipeline[i].OnTransitionFromCamera(
  542. fromCam, worldUp, deltaTime, ref m_Transitions))
  543. forceUpdate = true;
  544. }
  545. if (forceUpdate)
  546. {
  547. InternalUpdateCameraState(worldUp, deltaTime);
  548. InternalUpdateCameraState(worldUp, deltaTime);
  549. }
  550. else
  551. UpdateCameraState(worldUp, deltaTime);
  552. if (m_Transitions.m_OnCameraLive != null)
  553. m_Transitions.m_OnCameraLive.Invoke(this, fromCam);
  554. }
  555. /// <summary>
  556. /// Returns true, when the vcam has an extension or components that require input.
  557. /// </summary>
  558. internal override bool RequiresUserInput()
  559. {
  560. if (base.RequiresUserInput())
  561. return true;
  562. return m_ComponentPipeline != null && m_ComponentPipeline.Any(c => c != null && c.RequiresUserInput);
  563. }
  564. // This prevents the sensor size from dirtying the scene in the event of aspect ratio change
  565. internal override void OnBeforeSerialize()
  566. {
  567. if (!m_Lens.IsPhysicalCamera)
  568. m_Lens.SensorSize = Vector2.one;
  569. }
  570. }
  571. }