예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        /// <summary>
        /// Sets the view type to the object with the specified type.
        /// </summary>
        /// <param name="type">The type of the ViewType which should be set.</param>
        /// <param name="immediateTransition">Should the ViewType be transitioned immediately?</param>
        public void SetViewType(System.Type type, bool immediateTransition)
        {
            if ((m_ViewType != null && m_ViewType.GetType() == type) || type == null)
            {
                return;
            }

            // The ViewTypes may not be deserialized yet.
            if (m_ViewTypeNameMap.Count == 0)
            {
                DeserializeViewTypes();
            }

            int index;

            if (!m_ViewTypeNameMap.TryGetValue(type.FullName, out index))
            {
                Debug.LogError("Error: Unable to find the view type with name " + type.FullName);
                return;
            }

            float pitch = 0f, yaw = 0f;
            var   characterRotation = Quaternion.identity;

            // ViewType will be null on startup.
            if (m_ViewType != null && m_Character != null && Application.isPlaying)
            {
                pitch             = m_ViewType.Pitch;
                yaw               = m_ViewType.Yaw;
                characterRotation = m_ViewType.CharacterRotation;
                m_ViewType.ChangeViewType(false, 0, yaw, characterRotation);

                EventHandler.ExecuteEvent(m_GameObject, "OnCameraChangeViewTypes", m_ViewType, false);
                if (m_OnChangeViewTypesEvent != null)
                {
                    m_OnChangeViewTypesEvent.Invoke(m_ViewType, false);
                }
            }

            var originalViewType = m_ViewType;

            m_ViewTypeFullName = type.FullName;
            m_ViewType         = m_ViewTypes[index];

            // Keep the first/third person view type updated to be able to switch back to the last active type.
            if (m_ViewType.FirstPersonPerspective)
            {
                m_FirstPersonViewTypeFullName = m_ViewTypeFullName;
                m_FirstPersonViewType         = m_ViewType;
            }
            else
            {
                m_ThirdPersonViewTypeFullName = m_ViewTypeFullName;
                m_ThirdPersonViewType         = m_ViewType;
            }

            // If the original view type is not null then the view type has been changed at runtime. Transition to that new view type.
            if (originalViewType != null && m_Character != null && Application.isPlaying)
            {
                m_ViewType.ChangeViewType(true, pitch, yaw, characterRotation);

                EventHandler.ExecuteEvent(m_GameObject, "OnCameraChangeViewTypes", m_ViewType, true);
                if (m_OnChangeViewTypesEvent != null)
                {
                    m_OnChangeViewTypesEvent.Invoke(m_ViewType, true);
                }
                if (originalViewType.FirstPersonPerspective != m_ViewType.FirstPersonPerspective)
                {
                    EventHandler.ExecuteEvent <bool>(m_Character, "OnCameraWillChangePerspectives", m_ViewType.FirstPersonPerspective);
                }

                // Use the transitioner if it exists.
                if (!immediateTransition && m_Transitioner != null)
                {
                    // StartTransition will return success if the transition is started.
                    if (m_Transitioner.StartTransition(originalViewType, m_ViewType))
                    {
                        return;
                    }
                    else if (m_Transitioner.IsTransitioning)
                    {
                        m_Transitioner.StopTransition(false);
                    }
                }
                else
                {
                    // If there isn't a transitioner then immediately move to the target position.
                    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));
                    }
                }

                // Execute the perspective event if the transitioner does not exist or is not active. The transitioner will execute this event when it finishes.
                if (originalViewType.FirstPersonPerspective != m_ViewType.FirstPersonPerspective)
                {
                    EventHandler.ExecuteEvent <bool>(m_Character, "OnCameraChangePerspectives", m_ViewType.FirstPersonPerspective);

                    if (m_OnChangePerspectivesEvent != null)
                    {
                        m_OnChangePerspectivesEvent.Invoke(m_ViewType.FirstPersonPerspective);
                    }
                }
            }
        }