/// <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. SchedulerBase.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. var crateTransform = transform; m_SpawnedCrate = ObjectPoolBase.Instantiate(m_DestroyedCrate, crateTransform.position, crateTransform.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 = SchedulerBase.Schedule(maxDestroyTime, StopParticles); } }
/// <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> /// Instantiate the object. /// </summary> /// <param name="position">The position to instantiate the object at.</param> /// <param name="normal">The normal of the instantiated object.</param> /// <param name="gravityDirection">The normalized direction of the character's gravity.</param> /// <returns>The instantiated object (can be null). </returns> public GameObject Instantiate(Vector3 position, Vector3 normal, Vector3 gravityDirection) { if (m_Object == null) { return(null); } // There is a random chance that the object cannot be spawned. if (UnityEngine.Random.value < m_Probability) { var rotation = Quaternion.LookRotation(normal); // A random spin can be applied so the rotation isn't the same every hit. if (m_RandomSpin) { rotation *= Quaternion.AngleAxis(UnityEngine.Random.Range(0, 360), normal); } var instantiatedObject = ObjectPoolBase.Instantiate(m_Object, position, rotation); // If the DirectionalConstantForce component exists then the gravity direction should be set so the object will move in the correct direction. var directionalConstantForce = instantiatedObject.GetCachedComponent <Traits.DirectionalConstantForce>(); if (directionalConstantForce != null) { directionalConstantForce.Direction = gravityDirection; } return(instantiatedObject); } return(null); }
/// <summary> /// Perform the impact action. /// </summary> /// <param name="castID">The ID of the cast.</param> /// <param name="source">The object that caused the cast.</param> /// <param name="target">The object that was hit by the cast.</param> /// <param name="hit">The raycast that caused the impact.</param> protected override void ImpactInternal(uint castID, GameObject source, GameObject target, RaycastHit hit) { if (m_ParticlePrefab == null) { Debug.LogError("Error: A Particle Prefab must be specified.", m_MagicItem); return; } var rotation = Quaternion.LookRotation(hit.normal) * Quaternion.Euler(m_RotationOffset); var position = MathUtility.TransformPoint(hit.point, rotation, m_PositionOffset); if (m_CastIDParticleMap.TryGetValue(castID, out var existingParticleSystem)) { existingParticleSystem.transform.SetPositionAndRotation(position, rotation); return; } var obj = ObjectPoolBase.Instantiate(m_ParticlePrefab, position, rotation, m_ParentToImpactedObject ? target.transform : null); var particleSystem = obj.GetCachedComponent <ParticleSystem>(); if (particleSystem == null) { Debug.LogError($"Error: A Particle System must be specified on the particle {m_ParticlePrefab}.", m_MagicItem); return; } particleSystem.Clear(true); m_CastIDParticleMap.Add(castID, particleSystem); }
/// <summary> /// Initialize the default values. /// </summary> protected override void Awake() { base.Awake(); m_TrajectoryObject = GetComponent <TrajectoryObject>(); m_CharacterLocomotion = m_Character.GetCachedComponent <UltimateCharacterLocomotion>(); m_CharacterTransform = m_CharacterLocomotion.transform; #if ULTIMATE_CHARACTER_CONTROLLER_VR m_VRThrowableItem = GetComponent <IVRThrowableItem>(); #endif if (m_ThrownObject != null && m_TrajectoryObject != null) { // The object has to be instantiated for GetComponent to work. var instantiatedThrownObject = ObjectPoolBase.Instantiate(m_ThrownObject); var trajectoryCollider = instantiatedThrownObject.GetComponent <Collider>(); if (trajectoryCollider != null) { // Only sphere and capsules are supported. if (trajectoryCollider is SphereCollider) { var trajectorySphereCollider = trajectoryCollider as SphereCollider; var sphereCollider = m_GameObject.AddComponent <SphereCollider>(); sphereCollider.center = trajectorySphereCollider.center; sphereCollider.radius = trajectorySphereCollider.radius; sphereCollider.enabled = false; } else if (trajectoryCollider is CapsuleCollider) { var trajectoryCapsuleCollider = trajectoryCollider as CapsuleCollider; var capsuleCollider = m_GameObject.AddComponent <CapsuleCollider>(); capsuleCollider.center = trajectoryCapsuleCollider.center; capsuleCollider.radius = trajectoryCapsuleCollider.radius; capsuleCollider.height = trajectoryCapsuleCollider.height; capsuleCollider.direction = trajectoryCapsuleCollider.direction; capsuleCollider.enabled = false; } else { Debug.LogError($"Error: The collider of type {trajectoryCollider.GetType()} is not supported on the trajectory object " + m_ThrownObject.name); } m_GameObject.layer = LayerManager.SubCharacter; } ObjectPoolBase.Destroy(instantiatedThrownObject); } m_ThrowableItemPerpectiveProperties = m_ActivePerspectiveProperties as IThrowableItemPerspectiveProperties; if (m_ShowTrajectoryOnAim && m_TrajectoryObject == null) { Debug.LogError($"Error: A TrajectoryObject must be added to the {m_GameObject.name} GameObject in order for the trajectory to be shown."); } if (m_ThrownObject == null) { Debug.LogError($"Error: A ThrownObject must be assigned to the {m_GameObject.name} GameObject."); } EventHandler.RegisterEvent <bool, bool>(m_Character, "OnAimAbilityStart", OnAim); EventHandler.RegisterEvent(m_Character, "OnAnimatorReequipThrowableItem", ReequipThrowableItem); }
/// <summary> /// Starts the item use. /// </summary> /// <param name="itemAbility">The item ability that is using the item.</param> public override void StartItemUse(ItemAbility itemAbility) { base.StartItemUse(itemAbility); // An Animator Audio State Set may prevent the item from being used. if (!IsItemInUse()) { return; } if (!m_ThrowOnStopUse) { StartThrow(); } // Instantiate the object that will actually be thrown. var location = m_ThrowableItemPerpectiveProperties.ThrowLocation; m_InstantiatedThrownObject = ObjectPoolBase.Instantiate(m_ThrownObject, location.position, location.rotation, m_ObjectTransform.parent); m_InstantiatedThrownObject.transform.localScale = location.localScale; m_InstantiatedThrownObject.transform.SetLayerRecursively(m_StartLayer); m_InstantiatedTrajectoryObject = m_InstantiatedThrownObject.GetCachedComponent <TrajectoryObject>(); if (m_InstantiatedTrajectoryObject == null) { Debug.LogError($"Error: {m_TrajectoryObject.name} must contain the TrajectoryObject component."); return; } if (m_InstantiatedTrajectoryObject is Destructible) { (m_InstantiatedTrajectoryObject as Destructible).InitializeDestructibleProperties(m_DamageProcessor, m_DamageAmount, m_ImpactForce, m_ImpactForceFrames, m_ImpactLayers, m_ImpactStateName, m_ImpactStateDisableTimer, m_SurfaceImpact); } // The trajectory object will be enabled when the object is thrown. m_InstantiatedTrajectoryObject.enabled = false; // Hide the object that isn't thrown. EnableObjectMeshRenderers(false); // The instantiated object may not immediately be visible. if (m_DisableVisibleObject) { m_InstantiatedThrownObject.SetActive(false); m_ActivateVisibleObject = false; m_Item.SetVisibleObjectActive(false, true); if (m_ActivateThrowableObjectEvent.WaitForAnimationEvent) { EventHandler.RegisterEvent(m_Character, "OnAnimatorActivateThrowableObject", ActivateThrowableObject); } else { SchedulerBase.ScheduleFixed(m_ActivateThrowableObjectEvent.Duration, ActivateThrowableObject); } } }
/// <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 = Utility.MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset); var obj = ObjectPoolBase.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> /// The magic cast has collided with another object. /// </summary> /// <param name="hit">The raycast that caused the impact.</param> /// <param name="surfaceImpact">The type of particle that collided with the object.</param> private void MagicCastCollision(RaycastHit hit, SurfaceImpact surfaceImpact) { if (m_FlameParticle != null || (m_FlameImpact != null && m_FlameImpact != surfaceImpact)) { return; } // A fireball has collided with the crate. Start the flame. var crateTransform = transform; var flamePrefab = ObjectPoolBase.Instantiate(m_FlamePrefab, crateTransform.position, crateTransform.rotation); m_FlameParticle = flamePrefab.GetComponent <ParticleSystem>(); m_FlameParticleAudioSource = flamePrefab.GetCachedComponent <AudioSource>(); m_FlameParticleAudioSource.volume = 1; m_DamageTrigger.enabled = true; // The crate should be destroyed by the flame. ReduceHealth(); }
/// <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 = ObjectPoolBase.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> /// Spawns the particle. /// </summary> /// <param name="origin">The location that the cast originates from.</param> private void Spawn(Transform origin) { if (m_ParticlePrefab == null) { Debug.LogError("Error: A Particle Prefab must be specified.", m_MagicItem); return; } var obj = ObjectPoolBase.Instantiate(m_ParticlePrefab, MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset), origin.rotation * Quaternion.Euler(m_RotationOffset), m_ParentToOrigin ? origin : null); m_SpawnedTransform = obj.transform; var particleSystem = obj.GetCachedComponent <ParticleSystem>(); if (particleSystem == null) { Debug.LogError($"Error: A Particle System must be specified on the particle {m_ParticlePrefab}.", m_MagicItem); return; } particleSystem.Clear(true); }
/// <summary> /// Instantiates a new decal. /// </summary> /// <param name="original">The original prefab to spawn an instance of.</param> /// <param name="hit">The RaycastHit which caused the footprint to spawn.</param> /// <param name="rotation">The rotation of the decal which should be spawned.</param> /// <param name="scale">The scale of the decal to spawn.</param> /// <param name="allowedEdgeOverlap">How close to the edge the footprint is allowed to spawn.</param> /// <returns>The spawned decal. Can be null.</returns> private GameObject SpawnDecal(GameObject original, RaycastHit hit, Quaternion rotation, float scale, float allowedEdgeOverlap) { // Prevent z fighting by slightly raising the decal off of the surface. var decal = ObjectPoolBase.Instantiate(original, hit.point + (hit.normal * 0.001f), rotation); // Only set the decal parent to the hit transform on uniform objects to prevent stretching. if (MathUtility.IsUniform(hit.transform.localScale)) { decal.transform.parent = hit.transform; } if (scale != 1) { var vectorScale = Vector3.one; vectorScale.x = vectorScale.y = scale; decal.transform.localScale = vectorScale; } // Destroy the object if it cannot be cached. The object won't be able to be cached if it doesn't have all of the required components. if (!CacheMeshAndRenderer(decal)) { ObjectPoolBase.Destroy(decal); return(null); } // Do a test on the decal's quad to ensure all four corners are flush against a surface. This will prevent the decal from sticking out on an edge. if (allowedEdgeOverlap < 0.5f) { if (!DoQuadTest(decal, allowedEdgeOverlap)) { ObjectPoolBase.Destroy(decal); return(null); } } // The decal can be added. Add(decal); return(decal); }
/// <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> /// Drop an Item from the character. /// </summary> /// <param name="item">The item to drop.</param> /// <param name="forceDrop">Should the item be dropped even if the inventory doesn't contain any count for the item?</param> /// <param name="amount">The amount of ItemIdentifier that should be dropped.</param> /// <param name="remove">Should the item be removed after it is dropped?</param> /// <returns>The instance of the dropped item (can be null).</returns> public virtual GameObject DropItem(Item item, int amount, bool forceDrop, bool remove) { // The item needs to first be unequipped before it can be dropped. if (item.VisibleObjectActive && item.CharacterLocomotion.FirstPersonPerspective && remove) { item.UnequipDropAmount = amount; var itemObject = item.GetVisibleObject().transform; item.UnequpDropPosition = itemObject.position; item.UnequipDropRotation = itemObject.rotation; return(null); } GameObject spawnedObject = null; ItemPickupBase itemPickup = null; // If a drop prefab exists then the character should drop a prefab of the item so it can later be picked up. if (item.DropPrefab != null) { #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo == null || m_NetworkInfo.IsServer()) { #endif var existingAmount = GetItemIdentifierAmount(item.ItemIdentifier); if (existingAmount > 0) { // If the usable item prevents the item from being equipped when empty, and the usable item is empty, then the item // should not be dropped. for (int i = 0; i < item.ItemActions.Length; ++i) { var usableItem = (item.ItemActions[i] as UsableItem); if (usableItem != null && usableItem.GetConsumableItemIdentifier() != null && !usableItem.CanEquipEmptyItem && GetItemIdentifierAmount(usableItem.GetConsumableItemIdentifier()) == 0) { existingAmount = 0; break; } } } // The prefab can be dropped if the inventory contains the item or is force dropped. if (existingAmount > 0 || forceDrop) { Vector3 dropPosition; Quaternion dropRotation; // If the item is unequipped before it is dropped then it could be holstered so the current transform should not be used. if (item.UnequipDropAmount > 0) { dropPosition = item.UnequpDropPosition; dropRotation = item.UnequipDropRotation; } else { var itemObject = item.GetVisibleObject().transform; dropPosition = itemObject.position; dropRotation = itemObject.rotation; } spawnedObject = ObjectPoolBase.Instantiate(item.DropPrefab, dropPosition, dropRotation); // The ItemPickup component is responsible for allowing characters to pick up the item. Save the ItemIdentifier count // to the ItemIdentifierAmount array so that same amount can be picked up again. itemPickup = spawnedObject.GetCachedComponent <ItemPickupBase>(); if (itemPickup != null) { // Return the old. var itemDefinitionAmounts = itemPickup.GetItemDefinitionAmounts(); var itemDefinitionAmount = new ItemDefinitionAmount(item.ItemIdentifier.GetItemDefinition(), Mathf.Min(existingAmount, amount)); // If the dropped Item is a usable item then the array should be larger to be able to pick up the usable ItemIdentifier. var consumableItemIdentifiers = 0; UsableItem usableItem; if (item.DropConsumableItems) { for (int i = 0; i < item.ItemActions.Length; ++i) { if ((usableItem = (item.ItemActions[i] as UsableItem)) != null && usableItem.GetConsumableItemIdentifier() != null && usableItem.GetConsumableItemIdentifierAmount() != -1) { consumableItemIdentifiers++; } } } // Save the main ItemIdentifier. var length = consumableItemIdentifiers + 1; if (itemDefinitionAmounts.Length != length) { itemDefinitionAmounts = new ItemDefinitionAmount[length]; } itemDefinitionAmounts[0] = itemDefinitionAmount; // Save the usable ItemIdentifier if any exist. if (item.DropConsumableItems) { IItemIdentifier consumableItemIdentifier; consumableItemIdentifiers = 1; for (int i = 0; i < item.ItemActions.Length; ++i) { if ((usableItem = (item.ItemActions[i] as UsableItem)) != null && (consumableItemIdentifier = usableItem.GetConsumableItemIdentifier()) != null && usableItem.GetConsumableItemIdentifierAmount() != -1) { var consumableDropCount = 0; // Only remove the remaining inventory if there is just one ItemIdentifier remaining. This will allow the character to keep the consumable ammo // if only one item is dropped and the character has multiple of the same item. if (existingAmount == 1) { consumableDropCount = GetItemIdentifierAmount(consumableItemIdentifier); } var remainingConsumableAmount = usableItem.GetConsumableItemIdentifierAmount(); // The count may be negative (for use by the UI). var consumableDefinitionAmount = new ItemDefinitionAmount(consumableItemIdentifier.GetItemDefinition(), consumableDropCount + (remainingConsumableAmount > 0 ? remainingConsumableAmount : 0)); itemDefinitionAmounts[consumableItemIdentifiers] = consumableDefinitionAmount; consumableItemIdentifiers++; } } } // Enable the ItemPickup. itemPickup.SetItemDefinitionAmounts(itemDefinitionAmounts); itemPickup.Initialize(true); } // The ItemPickup may have a TrajectoryObject attached instead of a Rigidbody. var trajectoryObject = spawnedObject.GetCachedComponent <Objects.TrajectoryObject>(); if (trajectoryObject != null) { var velocity = item.CharacterLocomotion.Velocity; #if ULTIMATE_CHARACTER_CONTROLLER_VR if (item.HandHandler != null) { velocity += item.HandHandler.GetVelocity(item.SlotID) * item.DropVelocityMultiplier; } #endif trajectoryObject.Initialize(velocity, item.CharacterLocomotion.Torque.eulerAngles, item.Character); } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null) { Networking.Game.NetworkObjectPool.NetworkSpawn(item.DropPrefab, spawnedObject, true); } #endif } #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER } #endif } if (remove) { item.UnequipDropAmount = 0; RemoveItem(item.ItemIdentifier, item.SlotID, GetItemIdentifierAmount(item.ItemIdentifier), false); } if (item.DropItemEvent != null) { item.DropItemEvent.Invoke(); } return(spawnedObject); }
/// <summary> /// The object is no longer alive. /// </summary> /// <param name="position">The position of the damage.</param> /// <param name="force">The amount of force applied to the object while taking the damage.</param> /// <param name="attacker">The GameObject that killed the character.</param> public virtual void Die(Vector3 position, Vector3 force, GameObject attacker) { #if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER if (m_NetworkInfo != null && m_NetworkInfo.IsLocalPlayer()) { m_NetworkHealthMonitor.Die(position, force, attacker); } #endif // Spawn any objects on death, such as an explosion if the object is an explosive barrel. if (m_SpawnedObjectsOnDeath != null) { for (int i = 0; i < m_SpawnedObjectsOnDeath.Length; ++i) { var spawnedObject = ObjectPoolBase.Instantiate(m_SpawnedObjectsOnDeath[i], m_Transform.position, m_Transform.rotation); Explosion explosion; if ((explosion = spawnedObject.GetCachedComponent <Explosion>()) != null) { explosion.Explode(gameObject); } var rigidbodies = spawnedObject.GetComponentsInChildren <Rigidbody>(); for (int j = 0; j < rigidbodies.Length; ++j) { rigidbodies[j].AddForceAtPosition(force, position); } } } // Destroy any objects on death. The objects will be placed back in the object pool if they were created within it otherwise the object will be destroyed. if (m_DestroyedObjectsOnDeath != null) { for (int i = 0; i < m_DestroyedObjectsOnDeath.Length; ++i) { if (ObjectPoolBase.InstantiatedWithPool(m_DestroyedObjectsOnDeath[i])) { ObjectPoolBase.Destroy(m_DestroyedObjectsOnDeath[i]); } else { Object.Destroy(m_DestroyedObjectsOnDeath[i]); } } } // Change the layer to a death layer. if (m_DeathLayer.value != 0) { m_AliveLayer = m_GameObject.layer; m_GameObject.layer = m_DeathLayer; } // Play any take death audio. Use PlayAtPosition because the audio won't play if the GameObject is inactive. m_DeathAudioClipSet.PlayAtPosition(m_Transform.position); // Deactivate the object if requested. if (m_DeactivateOnDeath) { SchedulerBase.Schedule(m_DeactivateOnDeathDelay, Deactivate); } // The attributes shouldn't regenerate. if (m_ShieldAttribute != null) { m_ShieldAttribute.CancelAutoUpdate(); } if (m_HealthAttribute != null) { m_HealthAttribute.CancelAutoUpdate(); } // Notify those interested. EventHandler.ExecuteEvent <Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", position, force, attacker); if (m_OnDeathEvent != null) { m_OnDeathEvent.Invoke(position, force, attacker); } }