/// <summary> /// Determines if a controller is connected. /// </summary> private void CheckForController() { if (!CanCheckForController) { return; } var controllerConencted = Input.GetJoystickNames().Length > 0; if (m_ControllerConnected != controllerConencted) { m_ControllerConnected = controllerConencted; if (!string.IsNullOrEmpty(m_ConnectedControllerState)) { StateManager.SetState(gameObject, m_ConnectedControllerState, m_ControllerConnected); } EventHandler.ExecuteEvent <bool>(gameObject, "OnInputControllerConnected", m_ControllerConnected); } // Schedule the controller check event if the rate is positive. // UnityEngine.Input.GetJoystickNames generates garbage so limit the amount of time the controller is checked. if (m_ControllerConnectedCheckRate > 0 && (m_ControllerCheckEvent == null || !m_ControllerCheckEvent.Active)) { m_ControllerCheckEvent = Scheduler.Schedule(m_ControllerConnectedCheckRate, CheckForController); } }
/// <summary> /// The grenade should start to cook. /// </summary> /// <param name="originator">The object that instantiated the trajectory object.</param> public void StartCooking(GameObject originator) { SetOriginator(originator, Vector3.up); // The grenade should destruct after a specified amount of time. m_ScheduledDeactivation = Scheduler.Schedule(m_Lifespan, Deactivate); }
/// <summary> /// Initializes the spring. /// </summary> /// <param name="rotationalSpring">Is the spring used for rotations?</param> /// <param name="fixedUpdate">Should the event be invoked within the FixedUpdate loop? If false Update will be used.</param> public void Initialize(bool rotationalSpring, bool fixedUpdate) { if (!Application.isPlaying) { return; } // If the ScheduledEvent is null then the spring has already been initialized. if (m_ScheduledEvent != null) { return; } m_SoftForceFrames = new Vector3[m_MaxSoftForceFrames]; m_ScheduledEvent = fixedUpdate ? Scheduler.ScheduleFixed(-1, Tick) : Scheduler.Schedule(-1, Tick); m_VelocityFadeInEndTime = Time.time + m_VelocityFadeInLength; m_Resting = false; m_RotationalSpring = rotationalSpring; if (m_RotationalSpring) { m_RestValue.x = Utility.MathUtility.ClampInnerAngle(m_RestValue.x); m_RestValue.y = Utility.MathUtility.ClampInnerAngle(m_RestValue.y); m_RestValue.z = Utility.MathUtility.ClampInnerAngle(m_RestValue.z); } Reset(); }
/// <summary> /// The ability has stopped running. /// </summary> /// <param name="force">Was the ability force stopped?</param> protected override void AbilityStopped(bool force) { base.AbilityStopped(force); m_MoveTowardsLocation = null; if (force) { m_OnArriveAbility = null; } if (m_ForceStartEvent != null) { Scheduler.Cancel(m_ForceStartEvent); m_ForceStartEvent = null; } if (m_DisableGameplayInput) { EventHandler.ExecuteEvent(m_GameObject, "OnEnableGameplayInput", true); } // Reset the force independet look parameter set within StartAbility. EventHandler.ExecuteEvent(m_GameObject, "OnCharacterForceIndependentLook", false); // Start the OnArriveAbility after MoveTowards has stopped to prevent MoveTowards from affecting the arrive ability. if (m_OnArriveAbility != null) { m_CharacterLocomotion.TryStartAbility(m_OnArriveAbility, true, true); m_OnArriveAbility = null; } }
/// <summary> /// Determines the location to respawn the object to and then does the respawn. /// </summary> public void Respawn() { m_ScheduledRespawnEvent = null; if (m_PositioningMode != SpawnPositioningMode.None) { Vector3 position; Quaternion rotation; if (m_PositioningMode == SpawnPositioningMode.SpawnPoint) { position = m_Transform.position; rotation = m_Transform.rotation; // If the object can't be spawned then try again in the future. if (!SpawnPointManager.GetPlacement(m_GameObject, m_Grouping, ref position, ref rotation)) { m_ScheduledRespawnEvent = Scheduler.Schedule(Random.Range(m_MinRespawnTime, m_MaxRespawnTime), Respawn); return; } } else // Spawn Location. { position = m_StartPosition; rotation = m_StartRotation; } Respawn(position, rotation, true); } else { Respawn(m_Transform.position, m_Transform.rotation, false); } }
/// <summary> /// Adjusts the collider's center position by the specified amount. /// </summary> /// <param name="offset">The amont to adjust the center position by.</param> private void AdjustCenterOffset(Vector3 offset) { m_CapsuleCollider.center += offset; m_CapsuleCollider.height += offset.y / 2; if (!m_CharacterLocomotion.UsingHorizontalCollisionDetection) { return; } // Apply the offset if there are no collisions. var collisionEnabled = m_CharacterLocomotion.CollisionLayerEnabled; m_CharacterLocomotion.EnableColliderCollisionLayer(false); Vector3 firstEndCap, secondEndCap; MathUtility.CapsuleColliderEndCaps(m_CapsuleCollider, m_Transform.position, m_Transform.rotation, out firstEndCap, out secondEndCap); if (Physics.OverlapCapsuleNonAlloc(firstEndCap, secondEndCap, m_CapsuleCollider.radius * MathUtility.ColliderRadiusMultiplier(m_CapsuleCollider), m_OverlapColliders, m_CharacterLayerManager.SolidObjectLayers, QueryTriggerInteraction.Ignore) > 0) { m_CapsuleCollider.center -= offset; m_CapsuleCollider.height -= offset.y / 2; m_ColliderOffsetEvent = Scheduler.Schedule(Time.fixedDeltaTime, AdjustCenterOffset, offset); } m_CharacterLocomotion.EnableColliderCollisionLayer(collisionEnabled); }
/// <summary> /// Updates the action. /// </summary> public override void Update() { if (!m_Active) { return; } var active = false; for (int i = 0; i < m_Materials.Count; ++i) { var color = m_Materials[i].GetColor(m_ColorID); color.a = Mathf.MoveTowards(color.a, m_TargetAlpha, m_FadeSpeed); m_Materials[i].SetColor(m_ColorID, color); if (color.a != m_TargetAlpha) { active = true; } } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER // Update isn't called automatically for the remote players. if (active && m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer()) { m_UpdateEvent = SchedulerBase.Schedule(0.001f, Update); } #endif m_Active = active; }
/// <summary> /// Callback when the auto update event is executed. /// </summary> private void UpdateValue() { if (m_AutoUpdateValueType == AutoUpdateValue.Increase) { m_Value = Mathf.Min(m_Value + m_AutoUpdateAmount, m_MaxValue); if (m_Value < m_MaxValue) { m_AutoUpdateEvent = Scheduler.Schedule(m_AutoUpdateInterval, UpdateValue); } else { EventHandler.ExecuteEvent(this, "OnAttributeReachedDestinationValue"); } } else // Decrease. { m_Value = Mathf.Max(m_Value - m_AutoUpdateAmount, m_MinValue); if (m_Value > m_MinValue) { m_AutoUpdateEvent = Scheduler.Schedule(m_AutoUpdateInterval, UpdateValue); } else { EventHandler.ExecuteEvent(this, "OnAttributeReachedDestinationValue"); } } EventHandler.ExecuteEvent(m_GameObject, "OnAttributeUpdateValue", this); }
/// <summary> /// Fades all of the materials which belong to the renderers. /// </summary> /// <param name="interval">The time interval which updates the fade.</param> /// <param name="targetAlpha">The target alpha value.</param> private void FadeMaterials(float interval, float targetAlpha) { var arrived = true; for (int i = 0; i < m_Renderers.Length; ++i) { if (!m_Renderers[i].material.HasProperty(m_MaterialColorID)) { continue; } var color = m_Renderers[i].material.GetColor(m_MaterialColorID); color.a = Mathf.MoveTowards(color.a, targetAlpha, m_FadeStep); m_Renderers[i].material.SetColor(m_MaterialColorID, color); // Schedule the method again if the material isn't at the desired fade value. if (color.a != targetAlpha) { arrived = false; } } if (arrived) { m_FadeEvent = null; } else { m_FadeEvent = SchedulerBase.Schedule(interval, FadeMaterials, interval, targetAlpha); } }
/// <summary> /// Change the spring types to the specified type. /// </summary> /// <param name="type">The type to change the value to.</param> private void ChangeSpringType(SpringType type) { // Don't switch types if the type is equal to the current type or if the enable state event is active. This will occur if a new button is pressed // within the time that it takes to invoke the scheduled event. if (m_SpringType == type || m_EnableStateEvent != null) { return; } // Reset the button color and deactivate the previous character. The same character may be activated again depending on the spring type. if (m_SpringType != SpringType.None) { SetButtonColor((int)m_SpringType, m_NormalColor); if (m_ActiveCharacter != null) { m_ActiveCharacter.GetCachedComponent <UltimateCharacterLocomotion>().SetActive(false); StateManager.SetState(m_ActiveCharacter, System.Enum.GetName(typeof(SpringType), m_SpringType), false); } } // Remember the old spring type and activate the new. The button should reflect the selected spring type. var prevSpringType = m_SpringType; m_SpringType = type; SetButtonColor((int)m_SpringType, m_PressedColor); // If the previous spring type isn't None then a button was pressed. Activate the new character. if (prevSpringType != SpringType.None) { var prevCharacter = m_ActiveCharacter; // The active character depends on the spring type. if (m_SpringType == SpringType.Astronaut || m_SpringType == SpringType.DrunkPerson) { m_ActiveCharacter = m_DrunkAstronautCharacter; } else if (m_SpringType == SpringType.Giant) { m_ActiveCharacter = m_GiantCharacter; } else { m_ActiveCharacter = m_Character; } // Activate the correct character and set the camera to the character if that character changed. This shouldn't be done if the character didn't // change so the camera doesn't snap into position. var characterChange = m_ActiveCharacter != prevCharacter; m_ActiveCharacter.GetCachedComponent <UltimateCharacterLocomotion>().SetActive(true); if (characterChange) { m_CameraController.Character = m_ActiveCharacter; } // Wait a small amount of time if the springs are off so the item can get back into the correct position while the springs are enabled. m_EnableStateEvent = Scheduler.Schedule(m_SpringType == SpringType.SpringsOff ? 0.4f : 0, EnableSpringState, characterChange); } EnableInput(); }
/// <summary> /// Stops the cast. /// </summary> public override void Stop() { if (!m_Active) { return; } m_ParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmitting); // Optionally fade the particle out of the world. if (m_FadeOutDuration > 0) { if (m_FadeEvent != null) { SchedulerBase.Cancel(m_FadeEvent); m_FadeEvent = null; } if (m_Renderers == null) { m_Renderers = m_ParticleSystem.GetComponentsInChildren <ParticleSystemRenderer>(); } var interval = m_FadeOutDuration / (1 / m_FadeStep); // Reset the alpha if the renderers have no fade in duration. if (m_FadeInDuration == 0) { SetRendererAlpha(1); } m_FadeEvent = SchedulerBase.Schedule(interval, FadeMaterials, interval, 0f); } m_Active = false; base.Stop(); }
/// <summary> /// The effect has stopped running. /// </summary> protected override void EffectStopped() { base.EffectStopped(); SchedulerBase.Cancel(m_StopEvent); m_StopEvent = null; }
/// <summary> /// If the platform has arrived at the current waypoint then the next waypoint should be determined. /// </summary> private void UpdatePath() { if (GetRemainingDistance() < 0.01f && m_NextWaypointEvent == null && (m_MovementType != PathMovementType.Target || m_NextWaypoint != m_TargetWaypoint)) { m_NextWaypointEvent = SchedulerBase.ScheduleFixed(m_Waypoints[m_NextWaypoint].Delay, UpdateWaypoint); } }
/// <summary> /// An object has entered the trigger. /// </summary> /// <param name="other">The object that entered the trigger.</param> private void OnTriggerEnter(Collider other) { if (m_Health != null) { return; } // A main character collider is required. if (!MathUtility.InLayerMask(other.gameObject.layer, 1 << LayerManager.Character)) { return; } // The object must be a character. var characterLocomotion = other.GetComponentInParent <UltimateCharacterLocomotion>(); if (characterLocomotion == null) { return; } // With a health component. var health = characterLocomotion.GetComponent <Health>(); if (health == null) { return; } m_Health = health; m_HealthTransform = health.transform; m_ScheduledDamageEvent = Scheduler.Schedule(m_InitialDamageDelay, Damage); }
/// <summary> /// Reduces the health by the damage amount. /// </summary> private void ReduceHealth() { m_Health.Damage(m_DamageAmount.RandomValue); if (m_Health.IsAlive()) { // Keep reducing the object's health until is is no longer alive. Scheduler.Schedule(m_HealthReductionInterval.RandomValue, ReduceHealth); } else { // After the object is no longer alive spawn some wood shreds. These shreds should be cleaned up after a random // amount of time. m_SpawnedCrate = ObjectPool.Instantiate(m_DestroyedCrate, transform.position, transform.rotation); var maxDestroyTime = 0f; for (int i = 0; i < m_SpawnedCrate.transform.childCount; ++i) { var destroyTime = m_WoodShreadRemovalTime.RandomValue; if (destroyTime > maxDestroyTime) { maxDestroyTime = destroyTime; } Destroy(m_SpawnedCrate.transform.GetChild(i).gameObject, destroyTime); } m_StopEvent = Scheduler.Schedule(maxDestroyTime, StopParticles); } }
/// <summary> /// The ThrowableItem has been reequipped. /// </summary> private void ReequipThrowableItem() { if (!m_Reequipping) { return; } Scheduler.Cancel(m_ReequipEventBase); m_ReequipEventBase = null; m_Reequipping = false; m_Reequipped = true; m_ReequipFrame = Time.frameCount; // The item shouldn't be reequipped if it is out of ammo. if (m_Inventory != null && m_Inventory.GetItemIdentifierAmount(m_Item.ItemIdentifier) == 0) { return; } if (!m_DisableVisibleObject) { EnableObjectMeshRenderers(true); #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer()) { m_NetworkCharacter.EnableThrowableObjectMeshRenderers(this); } #endif } }
/// <summary> /// Performs the cast. /// </summary> /// <param name="origin">The location that the cast should spawn from.</param> /// <param name="direction">The direction of the cast.</param> /// <param name="targetPosition">The target position of the cast.</param> public override void Cast(Transform origin, Vector3 direction, Vector3 targetPosition) { if (m_AudioSource != null && m_FadeEvent == null) { return; } if (m_AudioClips == null || m_AudioClips.Length == 0) { Debug.LogError("Error: An Audio Clip must be specified.", m_MagicItem); return; } var audioClip = m_AudioClips[Random.Range(0, m_AudioClips.Length)]; if (audioClip == null) { Debug.Log("Error: The Audio Clip array has a null value."); return; } m_AudioSource = AudioManager.PlayAtPosition(audioClip, m_PlayAtOrigin ? origin.position : m_GameObject.transform.position); if (m_AudioSource != null) { m_AudioSource.volume = 1; m_AudioSource.loop = m_Loop; } if (m_FadeEvent != null) { Scheduler.Cancel(m_FadeEvent); m_FadeEvent = null; } }
/// <summary> /// Fades the message according to the fade speed. /// </summary> private void FadeMessage() { m_ObjectAlphaColor = Mathf.Max(m_ObjectAlphaColor - m_ObjectFadeSpeed, 0); if (m_ObjectAlphaColor == 0) { m_GameObject.SetActive(false); m_ShouldFade = false; m_ScheduledFade = null; m_ObjectPickup = null; return; } // Fade the text and icon. if (m_Text != null) { var color = m_Text.color; color.a = m_ObjectAlphaColor; m_Text.color = color; } if (m_Icon) { var color = m_Icon.color; color.a = m_ObjectAlphaColor; m_Icon.color = color; } // Keep fading until there is nothing left to fade. m_ScheduledFade = Scheduler.Schedule(0.01f, FadeMessage); }
/// <summary> /// Destroys the object. /// </summary> /// <param name="hit">The RaycastHit of the object. Can be null.</param> protected void Destruct(RaycastHit?hit) { if (m_Destroyed) { return; } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER // The object can only explode on the server. if (m_NetworkInfo != null && !m_NetworkInfo.IsServer()) { return; } #endif m_DestroyEvent = null; // The RaycastHit will be null if the destruction happens with no collision. var hitPosition = (hit != null && hit.HasValue) ? hit.Value.point : m_Transform.position; var hitNormal = (hit != null && hit.HasValue) ? hit.Value.normal : m_Transform.up; #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null && m_NetworkInfo.IsServer()) { m_DestructibleMonitor.Destruct(hitPosition, hitNormal); } #endif Destruct(hitPosition, hitNormal); }
/// <summary> /// The object has been disabled. /// </summary> public void OnDisable() { if (m_DestructionEvent != null) { Scheduler.Cancel(m_DestructionEvent); m_DestructionEvent = null; } }
/// <summary> /// Cancels the remove event. /// </summary> public void CancelRemoveEvent() { if (m_RemoveEvent != null) { Scheduler.Cancel(m_RemoveEvent); m_RemoveEvent = null; } }
/// <summary> /// Clears the delta drag position. /// </summary> private void DampenDeltaPosition() { m_DeltaPosition /= (1 + m_ActiveDragDamping); if (m_DeltaPosition.sqrMagnitude > 0.1f) { m_ActiveDragScheduler = Scheduler.Schedule(Time.fixedDeltaTime, DampenDeltaPosition); } }
/// <summary> /// Cancels the respawn. /// </summary> public void CancelRespawn() { if (m_ScheduledRespawnEvent != null) { Scheduler.Cancel(m_ScheduledRespawnEvent); m_ScheduledRespawnEvent = null; } }
/// <summary> /// Unregisters the object with the KinematicObjectManager. /// </summary> protected virtual void OnDisable() { if (m_NextWaypointEvent != null) { SchedulerBase.Cancel(m_NextWaypointEvent); m_NextWaypointEvent = null; } KinematicObjectManager.UnregisterKinematicObject(m_KinematicObjectIndex); }
/// <summary> /// Enables or disables the modifier. /// </summary> /// <param name="enable">Should the modifier be enabled?</param> public void EnableModifier(bool enable) { if (m_Attribute == null) { return; } // The attribute can be changed by a single value... if (enable && (!m_AutoUpdate || m_AutoUpdateStartDelay > 0)) { m_Attribute.Value += m_Amount; } if (!m_AutoUpdate || m_AutoUpdating == enable) { return; } // ...Or a change with a longer duration. m_AutoUpdating = enable; if (enable) { m_StoredAutoUpdateAmount = m_Attribute.AutoUpdateAmount; m_StoredAutoUpdateInterval = m_Attribute.AutoUpdateInterval; m_StoredAutoUpdateStartDelay = m_Attribute.AutoUpdateStartDelay; m_StoredAutoUpdateValueType = m_Attribute.AutoUpdateValueType; m_Attribute.AutoUpdateAmount = Mathf.Abs(m_Amount); m_Attribute.AutoUpdateInterval = m_AutoUpdateInterval; m_Attribute.AutoUpdateStartDelay = m_AutoUpdateStartDelay; m_Attribute.AutoUpdateValueType = m_Amount < 0 ? Attribute.AutoUpdateValue.Decrease : Attribute.AutoUpdateValue.Increase; m_Attribute.ScheduleAutoUpdate(m_AutoUpdateStartDelay); if (m_AutoUpdateDuration > 0) { m_DisableAutoUpdateEvent = Scheduler.Schedule(m_AutoUpdateDuration, EnableModifier, false); } } else { m_Attribute.AutoUpdateAmount = m_StoredAutoUpdateAmount; m_Attribute.AutoUpdateInterval = m_StoredAutoUpdateInterval; m_Attribute.AutoUpdateStartDelay = m_StoredAutoUpdateStartDelay; m_Attribute.AutoUpdateValueType = m_StoredAutoUpdateValueType; if (m_DisableAutoUpdateEvent != null) { Scheduler.Cancel(m_DisableAutoUpdateEvent); m_DisableAutoUpdateEvent = null; } m_Attribute.ScheduleAutoUpdate(m_StoredAutoUpdateStartDelay); } EventHandler.ExecuteEvent(this, "OnAttributeModifierAutoUpdateEnabled", this, enable); }
/// <summary> /// Destroys the spring. /// </summary> public void Destroy() { if (m_ScheduledEvent != null) { Scheduler.Cancel(m_ScheduledEvent); m_ScheduledEvent = null; } m_SoftForceFrames = null; }
/// <summary> /// The GameObject has been destroyed. /// </summary> protected virtual void OnDestroy() { if (m_ScheduledRespawnEvent != null) { Scheduler.Cancel(m_ScheduledRespawnEvent); m_ScheduledRespawnEvent = null; } EventHandler.UnregisterEvent <Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath); }
/// <summary> /// Schedules an auto update if the auto update value type is not set to none. /// </summary> /// <param name="delay">The amount to delay the attribute update event by.</param> private void ScheduleAutoUpdate(float delay) { Scheduler.Cancel(m_AutoUpdateEvent); if ((m_AutoUpdateValueType == AutoUpdateValue.Increase && m_Value != m_MaxValue) || (m_AutoUpdateValueType == AutoUpdateValue.Decrease && m_Value != m_MinValue)) { m_AutoUpdateEvent = Scheduler.Schedule(delay, UpdateValue); } }
/// <summary> /// Resets the gravity direction and align to gravity to their stopping values. /// </summary> protected void ResetAlignToGravity() { if (m_StopGravityDirection.sqrMagnitude > 0) { m_CharacterLocomotion.GravityDirection = m_StopGravityDirection.normalized; } // Wait a frame to allow the camera to reset its rotation. This is useful if the ability is stopped in a single frame. m_AlignToGravityReset = Scheduler.Schedule(Time.deltaTime * 2, DoAlignToGravityReset); }
/// <summary> /// The ability has started. /// </summary> protected override void AbilityStarted() { base.AbilityStarted(); if (!m_DamageVisualizationCompleteEvent.WaitForAnimationEvent) { m_CompleteEvent = SchedulerBase.Schedule(m_DamageVisualizationCompleteEvent.Duration, OnDamageVisualizationComplete); } }