/// <summary> /// Initialize the camera to follow the character. /// </summary> /// <param name="character">The character to initialize. Can be null.</param> private void InitializeCharacter(GameObject character) { #if UNITY_EDITOR if (!Application.isPlaying) { return; } #endif if (character == m_Character) { return; } // If the character is not null then the previous character should be notified that there is no longer a camera attached. if (m_Character != null) { EventHandler.ExecuteEvent <CameraController>(m_Character, "OnCharacterAttachCamera", null); EventHandler.ExecuteEvent <ILookSource>(m_Character, "OnCharacterAttachLookSource", null); EventHandler.UnregisterEvent <Vector3>(m_Character, "OnCameraPositionalForce", AddPositionalForce); EventHandler.UnregisterEvent <Vector3>(m_Character, "OnCameraRotationalForce", AddRotationalForce); EventHandler.UnregisterEvent <Vector3, Vector3, float>(m_Character, "OnAddSecondaryCameraForce", OnAddSecondaryForce); EventHandler.UnregisterEvent <bool>(m_Character, "OnCharacterImmediateTransformChange", OnImmediateTransformChange); EventHandler.UnregisterEvent(m_Character, "OnAnimatorSnapped", PositionImmediately); EventHandler.UnregisterEvent <Ability, bool>(m_Character, "OnCharacterAbilityActive", OnAbilityActive); EventHandler.UnregisterEvent <ItemAbility, bool>(m_Character, "OnCharacterItemAbilityActive", OnItemAbilityActive); EventHandler.UnregisterEvent <bool>(m_Character, "OnCameraChangePerspectives", OnChangePerspectives); StateManager.LinkGameObjects(m_Character, m_GameObject, false); } // The character should no longer be using the zoom state if the camera is no longer attached. if (m_Zoom && m_Character != null) { SetZoom(false); } // Set the character values. if (enabled = (character != null)) { m_Character = character; m_CharacterTransform = m_Character.transform; m_CharacterLocomotion = character.GetCachedComponent <UltimateCharacterLocomotion>(); m_CharacterInventory = character.GetCachedComponent <InventoryBase>(); InitializeAnchor(); } else { m_Character = null; m_CharacterTransform = null; m_CharacterLocomotion = null; m_CharacterInventory = null; } // Notify the view types of the character that is being attached. for (int i = 0; i < m_ViewTypes.Length; ++i) { m_ViewTypes[i].AttachCharacter(m_Character); } if (m_Character != null) { m_ViewType.ChangeViewType(true, 0, 0, m_CharacterTransform.rotation); if (m_ViewType.RotatePriority) { KinematicObjectManager.SetCameraRotation(m_KinematicObjectIndex, m_ViewType.Rotate(0, 0, true)); KinematicObjectManager.SetCameraPosition(m_KinematicObjectIndex, m_ViewType.Move(true)); } else { KinematicObjectManager.SetCameraPosition(m_KinematicObjectIndex, m_ViewType.Move(true)); KinematicObjectManager.SetCameraRotation(m_KinematicObjectIndex, m_ViewType.Rotate(0, 0, true)); } m_ViewType.UpdateFieldOfView(true); // Registered for any interested events. EventHandler.RegisterEvent <Vector3>(m_Character, "OnCameraPositionalForce", AddPositionalForce); EventHandler.RegisterEvent <Vector3>(m_Character, "OnCameraRotationalForce", AddRotationalForce); EventHandler.RegisterEvent <Vector3, Vector3, float>(m_Character, "OnAddSecondaryCameraForce", OnAddSecondaryForce); EventHandler.RegisterEvent <bool>(m_Character, "OnCharacterImmediateTransformChange", OnImmediateTransformChange); EventHandler.RegisterEvent(m_Character, "OnAnimatorSnapped", PositionImmediately); EventHandler.RegisterEvent <Ability, bool>(m_Character, "OnCharacterAbilityActive", OnAbilityActive); EventHandler.RegisterEvent <ItemAbility, bool>(m_Character, "OnCharacterItemAbilityActive", OnItemAbilityActive); EventHandler.RegisterEvent <bool>(m_Character, "OnCameraChangePerspectives", OnChangePerspectives); // Notify the camera components of the attached character. EventHandler.ExecuteEvent <GameObject>(m_GameObject, "OnCameraAttachCharacter", character); // Notify the character of the attached camera. EventHandler.ExecuteEvent <CameraController>(m_Character, "OnCharacterAttachCamera", this); EventHandler.ExecuteEvent <ILookSource>(m_Character, "OnCharacterAttachLookSource", this); EventHandler.ExecuteEvent <bool>(m_Character, "OnCameraWillChangePerspectives", m_ViewType.FirstPersonPerspective); EventHandler.ExecuteEvent <bool>(m_Character, "OnCameraChangePerspectives", m_ViewType.FirstPersonPerspective); StateManager.LinkGameObjects(m_Character, m_GameObject, true); #if UNITY_EDITOR // Show a warning if the movement type isn't what is recommended for the current view type. Only show this when the character is initially attached // because a mismatch is most likely when initially setting up the character. var recommendedMovementTypes = m_ViewType.GetType().GetCustomAttributes(typeof(RecommendedMovementType), true); if (recommendedMovementTypes != null && recommendedMovementTypes.Length > 0) { var movementType = m_CharacterLocomotion.ActiveMovementType; var isRecommendedMovementType = false; for (int i = 0; i < recommendedMovementTypes.Length; ++i) { var recommendedMovementType = recommendedMovementTypes[0] as RecommendedMovementType; if (recommendedMovementType.Type.IsInstanceOfType(movementType)) { isRecommendedMovementType = true; break; } } if (!isRecommendedMovementType) { Debug.LogWarning($"Warning: The {UnityEngineUtility.GetFriendlyName(movementType.GetType())} MovementType is active while the ViewType " + $"recommends using {UnityEngineUtility.GetFriendlyName((recommendedMovementTypes[0] as RecommendedMovementType).Type)}."); } } #endif } else { // Notify the camera components of the attached character. EventHandler.ExecuteEvent <GameObject>(m_GameObject, "OnCameraAttachCharacter", character); } }