/// <summary> /// Does the actual fire. /// </summary> public void Fire() { m_LastFireTime = Time.time; // Spawn a projectile which will move in the direction that the turret is facing var projectile = ObjectPoolBase.Instantiate(m_Projectile, m_FireLocation.position, m_Transform.rotation).GetCachedComponent <Projectile>(); projectile.Initialize(m_FireLocation.forward * m_VelocityMagnitude, Vector3.zero, null, m_DamageAmount, m_ImpactForce, m_ImpactForceFrames, m_ImpactLayers, string.Empty, 0, m_SurfaceImpact, m_GameObject); #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null) { NetworkObjectPool.NetworkSpawn(m_Projectile, projectile.gameObject, true); } #endif // Spawn a muzzle flash. if (m_MuzzleFlash) { var muzzleFlash = ObjectPoolBase.Instantiate(m_MuzzleFlash, m_MuzzleFlashLocation.position, m_MuzzleFlashLocation.rotation, m_Transform).GetCachedComponent <MuzzleFlash>(); muzzleFlash.Show(null, 0, true, null); } // Play a firing sound. if (m_FireAudioClip != null) { m_AudioSource.clip = m_FireAudioClip; m_AudioSource.Play(); } }
/// <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 ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER // The server will spawn the projectile. if (m_MagicItem.NetworkInfo != null) { if (m_MagicItem.NetworkInfo.IsLocalPlayer()) { m_MagicItem.NetworkCharacter.MagicCast(m_MagicItem, m_Index, m_CastID, direction, targetPosition); } if (!m_MagicItem.NetworkInfo.IsServer()) { return; } } #endif if (m_ProjectilePrefab == null) { Debug.LogError("Error: A Projectile Prefab must be specified", m_MagicItem); return; } var position = origin.TransformPoint(m_PositionOffset); if (targetPosition != position) { direction = (targetPosition - position).normalized; } var obj = ObjectPool.Instantiate(m_ProjectilePrefab, position, Quaternion.LookRotation(direction, m_CharacterLocomotion.Up) * Quaternion.Euler(m_RotationOffset), m_ParentToOrigin ? origin : null); var projectile = obj.GetComponent <MagicProjectile>(); if (projectile != null) { projectile.Initialize(direction * m_Speed, Vector3.zero, m_GameObject, m_MagicItem, m_CastID); } else { Debug.LogWarning($"Warning: The projectile {m_ProjectilePrefab.name} does not have the MagicProjectile component attached."); } var magicParticle = obj.GetComponent <MagicParticle>(); if (magicParticle != null) { magicParticle.Initialize(m_MagicItem, m_CastID); } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_MagicItem.NetworkInfo != null) { NetworkObjectPool.NetworkSpawn(m_ProjectilePrefab, obj, true); } #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_Object == null) { Debug.LogError("Error: An Object must be specified.", m_MagicItem); return; } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER // The local player will spawn the object if the object is a networked magic object. if (m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer()) { if (m_Object.GetComponent <INetworkMagicObject>() != null) { return; } } #endif var position = MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset); if (targetPosition != position) { direction = (targetPosition - position).normalized; } m_SpawnedObject = ObjectPool.Instantiate(m_Object, position, Quaternion.LookRotation(direction, m_CharacterLocomotion.Up) * Quaternion.Euler(m_RotationOffset), m_ParentToOrigin ? origin : null); #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_MagicItem.NetworkInfo != null && m_MagicItem.NetworkInfo.IsLocalPlayer()) { var networkMagicObject = m_SpawnedObject.GetComponent <INetworkMagicObject>(); if (networkMagicObject != null) { networkMagicObject.Instantiate(m_GameObject, m_MagicItem, m_Index, m_CastID); } NetworkObjectPool.NetworkSpawn(m_Object, m_SpawnedObject, false); } #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 ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_MagicItem.NetworkInfo != null && m_MagicItem.NetworkInfo.IsLocalPlayer()) { m_MagicItem.NetworkCharacter.MagicCast(m_MagicItem, m_Index, m_CastID, direction, targetPosition); } #endif var position = MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset); if (targetPosition != position) { direction = (targetPosition - position).normalized; } if (m_ProjectDirectionOnPlane) { direction = Vector3.ProjectOnPlane(direction, m_CharacterLocomotion.Up); } // The direction can't be 0. if (direction.sqrMagnitude == 0) { direction = m_CharacterLocomotion.transform.forward; } var rotation = Quaternion.LookRotation(direction, m_CharacterLocomotion.Up) * Quaternion.Euler(m_RotationOffset); // If the cast is currently active then the particle should be reused. if (m_Active) { if (m_SetRendererLengthScale) { SetRendererLength(origin.position, targetPosition); } if (!m_ParentToOrigin) { m_ParticleTransform.position = position; } m_ParticleTransform.rotation = rotation; return; } if (m_ParticlePrefab == null) { Debug.LogError("Error: A Particle Prefab must be specified.", m_MagicItem); return; } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER // The local player will spawn the particle if the object is a networked magic object. if (m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer()) { if (m_ParticlePrefab.GetComponent <INetworkMagicObject>() != null) { return; } } #endif if (m_FadeEvent != null) { SchedulerBase.Cancel(m_FadeEvent); m_FadeEvent = null; SetRendererAlpha(0); } var obj = ObjectPoolBase.Instantiate(m_ParticlePrefab, position, rotation, m_ParentToOrigin ? origin : null); m_ParticleTransform = obj.transform; m_ParticleTransform.SetLayerRecursively(m_ParticleLayer); m_ParticleSystem = obj.GetCachedComponent <ParticleSystem>(); if (m_ParticleSystem == null) { Debug.LogError($"Error: A Particle System must be specified on the particle {m_ParticlePrefab}.", m_MagicItem); return; } m_ParticleSystem.Clear(true); m_Renderers = null; if (m_SetRendererLengthScale) { SetRendererLength(origin.position, targetPosition); } StartMaterialFade(obj); // The MagicParticle can determine the impacts. var magicParticle = obj.GetComponent <MagicParticle>(); if (magicParticle != null) { magicParticle.Initialize(m_MagicItem, m_CastID); } m_Active = true; #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_MagicItem.NetworkInfo != null && m_MagicItem.NetworkInfo.IsLocalPlayer()) { var networkMagicObject = obj.GetComponent <INetworkMagicObject>(); if (networkMagicObject != null) { networkMagicObject.Instantiate(m_GameObject, m_MagicItem, m_Index, m_CastID); } NetworkObjectPool.NetworkSpawn(m_ParticlePrefab, obj, false); } #endif }
/// <summary> /// Throws the throwable object. /// </summary> public void ThrowItem() { if (m_Thrown) { return; } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER // The object has been thrown. If the ItemAction is on the server then that object should be spawned on the network. // Non-server actions should disable the mesh renderers so the object can take its place. The mesh renderers will be enabled again in a separate call. if (m_NetworkInfo != null) { EnableObjectMeshRenderers(false); if (!m_NetworkInfo.IsServer()) { ObjectPool.Destroy(m_InstantiatedThrownObject); m_InstantiatedThrownObject = null; return; } } #endif m_InstantiatedThrownObject.transform.parent = null; // The collider was previously disabled. Enable it again when it is thrown. var collider = m_InstantiatedThrownObject.GetCachedComponent <Collider>(); collider.enabled = true; // When the item is used the trajectory object should start moving on its own. // The throwable item may be on the other side of an object (especially in the case of separate arms for the first person perspective). Perform a linecast // to ensure the throwable item doesn't move through any objects. var collisionEnabled = m_CharacterLocomotion.CollisionLayerEnabled; m_CharacterLocomotion.EnableColliderCollisionLayer(false); if (!m_CharacterLocomotion.ActiveMovementType.UseIndependentLook(false) && Physics.Linecast(m_CharacterLocomotion.LookSource.LookPosition(), m_InstantiatedTrajectoryObject.transform.position, out m_RaycastHit, m_ImpactLayers, QueryTriggerInteraction.Ignore)) { m_InstantiatedTrajectoryObject.transform.position = m_RaycastHit.point; } m_CharacterLocomotion.EnableColliderCollisionLayer(collisionEnabled); var trajectoryTransform = m_ThrowableItemPerpectiveProperties.TrajectoryLocation != null ? m_ThrowableItemPerpectiveProperties.TrajectoryLocation : m_CharacterTransform; var lookDirection = m_LookSource.LookDirection(trajectoryTransform.TransformPoint(m_TrajectoryOffset), false, m_ImpactLayers, true, true); #if ULTIMATE_CHARACTER_CONTROLLER_VR if (m_VRThrowableItem != null && m_CharacterLocomotion.FirstPersonPerspective) { m_Velocity = m_VRThrowableItem.GetVelocity(); } #endif var velocity = MathUtility.TransformDirection(m_Velocity, Quaternion.LookRotation(lookDirection, m_CharacterLocomotion.Up)); // Prevent the item from being thrown behind the character. This can happen if the character is looking straight up and there is a positive // y velocity. Gravity will cause the thrown object to go in the opposite direction. if (Vector3.Dot(velocity.normalized, m_CharacterTransform.forward) < 0 && m_CharacterTransform.InverseTransformDirection(velocity.normalized).y > 0) { velocity = m_CharacterTransform.up * velocity.magnitude; } m_InstantiatedTrajectoryObject.Initialize(m_CharacterLocomotion.Alive ? (velocity + (m_CharacterTransform.forward * m_CharacterLocomotion.LocalVelocity.z)) : Vector3.zero, Vector3.zero, m_Character, false); #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null) { NetworkObjectPool.NetworkSpawn(m_ThrownObject, m_InstantiatedThrownObject, true); } #endif // Optionally change the layer after the object has been thrown. This allows the object to change from the first person Overlay layer // to the Default layer after it has cleared the character's hands. if (m_StartLayer != m_ThrownLayer) { Scheduler.ScheduleFixed(m_LayerChangeDelay, ChangeThrownLayer, m_InstantiatedThrownObject); } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null && !m_NetworkInfo.IsLocalPlayer()) { m_Thrown = true; } #endif }
/// <summary> /// Throws the throwable object. /// </summary> public void ThrowItem() { // m_InstantiatedThrownObject will be null for remote players on the network. if (m_InstantiatedThrownObject != null) { m_InstantiatedThrownObject.transform.parent = null; // The collider was previously disabled. Enable it again when it is thrown. var collider = m_InstantiatedThrownObject.GetCachedComponent <Collider>(); collider.enabled = true; // When the item is used the trajectory object should start moving on its own. if (m_InstantiatedTrajectoryObject != null) { // The throwable item may be on the other side of an object (especially in the case of separate arms for the first person perspective). Perform a linecast // to ensure the throwable item doesn' move through any objects. if (!m_CharacterLocomotion.ActiveMovementType.UseIndependentLook(false) && Physics.Linecast(m_CharacterLocomotion.LookSource.LookPosition(), m_InstantiatedTrajectoryObject.transform.position, out m_RaycastHit, m_ImpactLayers, QueryTriggerInteraction.Ignore)) { m_InstantiatedTrajectoryObject.transform.position = m_RaycastHit.point; } var trajectoryTransform = m_ThrowableItemPerpectiveProperties.TrajectoryLocation != null ? m_ThrowableItemPerpectiveProperties.TrajectoryLocation : m_CharacterTransform; var lookDirection = m_LookSource.LookDirection(trajectoryTransform.TransformPoint(m_TrajectoryOffset), false, m_ImpactLayers, true); #if ULTIMATE_CHARACTER_CONTROLLER_VR if (m_VRThrowableItem != null && m_CharacterLocomotion.FirstPersonPerspective) { m_Velocity = m_VRThrowableItem.GetVelocity(); } #endif var velocity = MathUtility.TransformDirection(m_Velocity, Quaternion.LookRotation(lookDirection, m_CharacterLocomotion.Up)); // Prevent the item from being thrown behind the character. This can happen if the character is looking straight up and there is a positive // y velocity. Gravity will cause the thrown object to go in the opposite direction. if (Vector3.Dot(velocity.normalized, m_CharacterTransform.forward) < 0) { velocity = m_CharacterTransform.up * velocity.magnitude; } m_InstantiatedTrajectoryObject.Initialize(velocity + (m_CharacterTransform.forward * m_CharacterLocomotion.LocalVelocity.z), Vector3.zero, m_Character, false); } } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null) { // The object has been thrown. If the ItemAction is local then that object should be spawned on the network. // Non-local actions should disable the mesh renderers so the object can take its place. The mesh renderers will be enabled again in a separate call. if (m_NetworkInfo.IsLocalPlayer()) { NetworkObjectPool.NetworkSpawn(m_ThrownObject, m_InstantiatedThrownObject); } else { EnableObjectMeshRenderers(false); } } #endif if (m_Inventory != null) { m_Inventory.UseItem(m_ConsumableItemType, 1); } }