Update
This commit is contained in:
@@ -1,232 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.Character;
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Controls the animation for the door.
|
||||
/// </summary>
|
||||
public class Door : MonoBehaviour
|
||||
{
|
||||
private const string c_ColorText = "_Color";
|
||||
private const string c_EmissionColor = "_EmissionColor";
|
||||
|
||||
[Tooltip("The LayerMask of the character.")]
|
||||
[SerializeField] protected LayerMask m_LayerMask = 1 << LayerManager.Character;
|
||||
[Tooltip("Is the door locked?")]
|
||||
[SerializeField] protected bool m_Locked = false;
|
||||
[Tooltip("Should the door be permanently locked? A permanently locked door cannot be opened by the DemoManager.")]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("m_PermantlyLocked")]
|
||||
[SerializeField] protected bool m_PermanentlyLocked;
|
||||
[Tooltip("Should the door be opened at the start?")]
|
||||
[SerializeField] protected bool m_OpenAtStart;
|
||||
[Tooltip("Should the door close when the character leaves the trigger?")]
|
||||
[SerializeField] protected bool m_CloseOnTriggerExit = true;
|
||||
[Tooltip("The material that can change colors when the door is locked or unlcoked.")]
|
||||
[SerializeField] protected Material m_StatusMaterial;
|
||||
[Tooltip("The color of the closed door.")]
|
||||
[SerializeField] protected Color m_LockedColor = Color.red;
|
||||
[Tooltip("The color of the opened door.")]
|
||||
[SerializeField] protected Color m_UnlockedColor = Color.green;
|
||||
[Tooltip("The AudioClip that should play when the door is opened.")]
|
||||
[SerializeField] protected AudioClip m_OpenAudioClip;
|
||||
[Tooltip("The AudioClip that should play when the door is closed.")]
|
||||
[SerializeField] protected AudioClip m_CloseAudioClip;
|
||||
|
||||
public bool Locked { get { return m_Locked; }
|
||||
set {
|
||||
if (m_Locked == value) {
|
||||
return;
|
||||
}
|
||||
m_Locked = value;
|
||||
UpdateDoorStatus();
|
||||
if (m_Locked && m_Open) {
|
||||
OpenClose(false, true, true);
|
||||
} else if (!m_Locked && m_CharacterCount > 0) {
|
||||
m_Open = false;
|
||||
OpenClose(true, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool PermanentlyLocked { get { return m_PermanentlyLocked; } set { m_PermanentlyLocked = value; } }
|
||||
public bool CloseOnTriggerExit { get { return m_CloseOnTriggerExit; } set { m_CloseOnTriggerExit = value; } }
|
||||
|
||||
private static int s_OpenHash = Animator.StringToHash("Open");
|
||||
|
||||
private Animator m_Animator;
|
||||
private AudioSource m_AudioSource;
|
||||
|
||||
private bool m_ManagerOpen;
|
||||
private bool m_Open;
|
||||
private int m_CharacterCount;
|
||||
private Material[] m_StatusMaterials;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Animator = GetComponent<Animator>();
|
||||
m_AudioSource = GetComponent<AudioSource>();
|
||||
|
||||
var demoManager = FindObjectOfType<DemoManager>();
|
||||
if (demoManager != null) {
|
||||
demoManager.RegisterDoor(this);
|
||||
}
|
||||
|
||||
// Cache the light materials so they can be changed.
|
||||
var renderers = GetComponentsInChildren<Renderer>();
|
||||
for (int i = 0; i < renderers.Length; ++i) {
|
||||
var materials = renderers[i].sharedMaterials;
|
||||
for (int j = 0; j < materials.Length; ++j) {
|
||||
// The shared material will allow for a valid comparison. The instance material should not be compared.
|
||||
if (materials[j] != m_StatusMaterial) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_StatusMaterials == null) {
|
||||
m_StatusMaterials = new Material[1];
|
||||
} else {
|
||||
System.Array.Resize(ref m_StatusMaterials, m_StatusMaterials.Length + 1);
|
||||
}
|
||||
|
||||
// Cache the instance material so each status light operates independently.
|
||||
m_StatusMaterials[m_StatusMaterials.Length - 1] = renderers[i].materials[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Permantly locked doors cannot be opened.
|
||||
if (m_PermanentlyLocked) {
|
||||
m_Locked = true;
|
||||
}
|
||||
if (m_OpenAtStart) {
|
||||
OpenClose(true, true, false);
|
||||
}
|
||||
UpdateDoorStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the door status material.
|
||||
/// </summary>
|
||||
private void UpdateDoorStatus()
|
||||
{
|
||||
if (m_StatusMaterials != null) {
|
||||
for (int i = 0; i < m_StatusMaterials.Length; ++i) {
|
||||
var locked = m_Locked || m_PermanentlyLocked;
|
||||
m_StatusMaterials[i].SetColor(c_ColorText, locked ? m_LockedColor : m_UnlockedColor);
|
||||
m_StatusMaterials[i].SetColor(c_EmissionColor, locked ? m_LockedColor : m_UnlockedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the door.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
OpenClose(false, false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the door.
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
OpenClose(true, false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens or closes the door.
|
||||
/// </summary>
|
||||
/// <param name="open">Should the door be opened?</param>
|
||||
/// <param name="fromManager">Is the door being opened or closed from the DemoManager?</param>
|
||||
/// <param name="playAudio">Should the door open/close audio be played?</param>
|
||||
public void OpenClose(bool open, bool fromManager, bool playAudio)
|
||||
{
|
||||
// Permanently locked doors cannot be opened.
|
||||
if (m_PermanentlyLocked && open) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't close the door if the manager opened the door.
|
||||
if (!open && !fromManager && m_ManagerOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The door can't open if it is already open.
|
||||
if (m_Open == open) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (open) {
|
||||
// The door can't open if it's locked.
|
||||
if (m_Locked) {
|
||||
// The manager can unlock the door.
|
||||
if (fromManager) {
|
||||
m_Locked = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Open = open;
|
||||
|
||||
m_Animator.SetBool(s_OpenHash, open);
|
||||
if (playAudio && m_AudioSource != null) {
|
||||
if (open && m_OpenAudioClip != null) {
|
||||
m_AudioSource.clip = m_OpenAudioClip;
|
||||
m_AudioSource.Play();
|
||||
} else if (!open && m_CloseAudioClip != null) {
|
||||
m_AudioSource.clip = m_CloseAudioClip;
|
||||
m_AudioSource.Play();
|
||||
}
|
||||
}
|
||||
|
||||
// The manager will override the trigger settings.
|
||||
if (fromManager) {
|
||||
m_ManagerOpen = open;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the door if the character enters the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider which entered the trigger.</param>
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, m_LayerMask) || other.gameObject.GetCachedParentComponent<UltimateCharacterLocomotion>() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_CharacterCount++;
|
||||
OpenClose(true, false, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the door if the character leaves the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider which left the trigger.</param>
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, m_LayerMask) || other.gameObject.GetCachedParentComponent<UltimateCharacterLocomotion>() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The door should only close when all characters are no longer within the trigger.
|
||||
m_CharacterCount--;
|
||||
if (m_CharacterCount == 0 && m_Animator.GetBool(s_OpenHash) && m_CloseOnTriggerExit) {
|
||||
OpenClose(false, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aed02a211391a924f8e90218cdd5641a
|
||||
timeCreated: 1520644758
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 10100
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,163 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.Shared.Events;
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.Traits;
|
||||
using Opsive.UltimateCharacterController.SurfaceSystem;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A flammable crate will play a flame particle if it gets hit by a fireball.
|
||||
/// </summary>
|
||||
public class FlammableCrate : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The SurfaceImpact that causes the flame to start.")]
|
||||
[SerializeField] protected SurfaceImpact m_FlameImpact;
|
||||
[Tooltip("A reference to the flame particle that should start when the fireball collides with the crate.")]
|
||||
[SerializeField] protected GameObject m_FlamePrefab;
|
||||
[Tooltip("The crate that is spawned with the wood shreds.")]
|
||||
[SerializeField] protected GameObject m_DestroyedCrate;
|
||||
[Tooltip("The interval that the object should have its health reduced.")]
|
||||
[SerializeField] protected MinMaxFloat m_HealthReductionInterval = new MinMaxFloat(0.2f, 0.8f);
|
||||
[Tooltip("The amount that the object should be damaged on each interval.")]
|
||||
[SerializeField] protected MinMaxFloat m_DamageAmount = new MinMaxFloat(4, 10);
|
||||
[Tooltip("The amount of time it takes for the wood shreds to be removed.")]
|
||||
[SerializeField] protected MinMaxFloat m_WoodShreadRemovalTime = new MinMaxFloat(5, 7);
|
||||
[Tooltip("The amount to fade out the AudioSource.")]
|
||||
[SerializeField] protected float m_AudioSourceFadeAmount = 0.05f;
|
||||
|
||||
private BoxCollider m_DamageTrigger;
|
||||
private Health m_Health;
|
||||
private ParticleSystem m_FlameParticle;
|
||||
private AudioSource m_FlameParticleAudioSource;
|
||||
private GameObject m_SpawnedCrate;
|
||||
private ScheduledEventBase m_StopEvent;
|
||||
|
||||
private float m_StartHealth;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Health = GetComponent<Health>();
|
||||
m_StartHealth = m_Health.HealthValue;
|
||||
|
||||
// A box collider will be a trigger which damages the character if they stop within the flames.
|
||||
var colliders = GetComponents<BoxCollider>();
|
||||
for (int i = 0; i < colliders.Length; ++i) {
|
||||
if (!colliders[i].isTrigger) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_DamageTrigger = colliders[i];
|
||||
m_DamageTrigger.enabled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
EventHandler.RegisterEvent<RaycastHit, SurfaceImpact>(gameObject, "OnMagicCastCollision", MagicCastCollision);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The crate has been enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
StopParticles();
|
||||
if (m_Health.HealthValue != m_StartHealth) {
|
||||
m_Health.Heal(m_StartHealth - m_Health.HealthValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 flamePrefab = ObjectPool.Instantiate(m_FlamePrefab, transform.position, transform.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>
|
||||
/// 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 crate has been destroyed. Stop the particles.
|
||||
/// </summary>
|
||||
private void StopParticles()
|
||||
{
|
||||
if (m_StopEvent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Scheduler.Cancel(m_StopEvent);
|
||||
m_StopEvent = null;
|
||||
m_DamageTrigger.enabled = false;
|
||||
m_FlameParticle.Stop(true);
|
||||
m_FlameParticle = null;
|
||||
Scheduler.Schedule(0.2f, FadeAudioSource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fades the flame audio source.
|
||||
/// </summary>
|
||||
private void FadeAudioSource()
|
||||
{
|
||||
m_FlameParticleAudioSource.volume -= m_AudioSourceFadeAmount;
|
||||
if (m_FlameParticleAudioSource.volume > 0) {
|
||||
Scheduler.Schedule(0.2f, FadeAudioSource);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The object has been destroyed.
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
EventHandler.UnregisterEvent<RaycastHit, SurfaceImpact>(gameObject, "OnMagicCastCollision", MagicCastCollision);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac8e2615485f28345a3d5afb697b94eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,75 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.Shared.Events;
|
||||
using Opsive.UltimateCharacterController.Traits;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A healing crate will update its material if it is healed.
|
||||
/// </summary>
|
||||
public class HealingCrate : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The material representing a damaged crate.")]
|
||||
[SerializeField] protected Material m_DamagedMaterial;
|
||||
[Tooltip("The material representing a healed crate.")]
|
||||
[SerializeField] protected Material m_HealedMaterial;
|
||||
[Tooltip("The crate is healed when the Health attribute is greater than the specified value.")]
|
||||
[SerializeField] protected float m_HealedAttributeValue = 40;
|
||||
|
||||
private Renderer m_Renderer;
|
||||
private Attribute m_HealthAttribute;
|
||||
private float m_StartingAttributeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Renderer = gameObject.GetComponent<Renderer>();
|
||||
var attributeManager = gameObject.GetComponent<AttributeManager>();
|
||||
m_HealthAttribute = attributeManager.GetAttribute("Health");
|
||||
m_StartingAttributeValue = m_HealthAttribute.Value;
|
||||
|
||||
EventHandler.RegisterEvent<Attribute>(gameObject, "OnAttributeUpdateValue", OnUpdateValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The attribute value has beeen updated.
|
||||
/// </summary>
|
||||
/// <param name="attribute">The attribute that has been updated.</param>
|
||||
private void OnUpdateValue(Attribute attribute)
|
||||
{
|
||||
if (attribute != m_HealthAttribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (attribute.Value >= m_HealedAttributeValue) {
|
||||
m_Renderer.sharedMaterial = m_HealedMaterial;
|
||||
} else {
|
||||
m_Renderer.sharedMaterial = m_DamagedMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Revert the health attribute value when the object is disabled.
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
m_HealthAttribute.Value = m_StartingAttributeValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The object has been destroyed.
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
EventHandler.UnregisterEvent<Attribute>(gameObject, "OnAttributeUpdateValue", OnUpdateValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9291b59f45e20e47aaee07384c8f32c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,59 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Traits;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Instantly kills the character if the character moves beneath the moving platform as it is moving down.
|
||||
/// </summary>
|
||||
public class MovingPlatformDeathZone : MonoBehaviour
|
||||
{
|
||||
private Transform m_Transform;
|
||||
private Vector3 m_PrevPosition;
|
||||
private bool m_DownwardMovement;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Transform = transform;
|
||||
m_PrevPosition = m_Transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detect if the platform is moving downward.
|
||||
/// </summary>
|
||||
private void FixedUpdate()
|
||||
{
|
||||
m_DownwardMovement = m_Transform.InverseTransformDirection(m_Transform.position - m_PrevPosition).y < 0;
|
||||
m_PrevPosition = m_Transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
// The platform has to be moving downward in order to kill the player.
|
||||
if (!m_DownwardMovement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Kill the character.
|
||||
var health = other.GetComponentInParent<CharacterHealth>();
|
||||
if (health == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
health.ImmediateDeath(m_Transform.position, Vector3.down, (m_Transform.position - m_PrevPosition).magnitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53cde399db556304bb9a0a4f6bb87c49
|
||||
timeCreated: 1543825614
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,44 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A particle stream crate will reset its position when the crate reactivates.
|
||||
/// </summary>
|
||||
public class ParticleStreamCrate : MonoBehaviour
|
||||
{
|
||||
private Rigidbody m_Rigibody;
|
||||
|
||||
private Vector3 m_Position;
|
||||
private Quaternion m_Rotation;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Rigibody = GetComponent<Rigidbody>();
|
||||
|
||||
m_Position = transform.position;
|
||||
m_Rotation = transform.rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The crate has been enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
m_Rigibody.linearVelocity = Vector3.zero;
|
||||
m_Rigibody.angularVelocity = Vector3.zero;
|
||||
|
||||
transform.position = m_Position;
|
||||
transform.rotation = m_Rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3af4c96da50a1da4f8996cf0396d1062
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,43 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The ShieldBubble will play an enlarging animation when the object spawns.
|
||||
/// </summary>
|
||||
public class ShieldBubble : MonoBehaviour
|
||||
{
|
||||
private Transform m_Transform;
|
||||
private Animator m_Animator;
|
||||
|
||||
private Vector3 m_Scale;
|
||||
private int m_DefaultStateHash;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Transform = GetComponent<Transform>();
|
||||
m_Animator = GetComponent<Animator>();
|
||||
|
||||
m_Scale = m_Transform.localScale;
|
||||
m_DefaultStateHash = Animator.StringToHash("EnlargingBubble");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the changed values.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
m_Animator.Play(m_DefaultStateHash, 0, 0);
|
||||
m_Transform.localScale = m_Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a1c0907934723149b1704eb399e2163
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,85 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Character;
|
||||
using Opsive.UltimateCharacterController.Character.Abilities;
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Moves the platform between two points. This gives an example of using the Move With Object ability and moving on an object that is
|
||||
/// updated outside of the Kinematic Object Manager update loop.
|
||||
/// </summary>
|
||||
public class SimplePlatform : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The position that the platform should move towards when the character is not on top of it.")]
|
||||
[SerializeField] protected Vector3 m_RestingPosition;
|
||||
[Tooltip("The position that the platform should move towards when the character is on top of it.")]
|
||||
[SerializeField] protected Vector3 m_ActivePosition;
|
||||
[Tooltip("The speed that the platform should move.")]
|
||||
[SerializeField] protected float m_MoveSpeed = 0.05f;
|
||||
|
||||
private Transform m_Transform;
|
||||
private MoveWithObject m_MoveWithObjectAbility;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_Transform = transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Teleport the character to the specified destination.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider that entered the trigger. May or may not be a character.</param>
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, 1 << LayerManager.Character)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UltimateCharacterLocomotion characterLocomotion;
|
||||
if ((characterLocomotion = other.GetComponentInParent<UltimateCharacterLocomotion>()) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_MoveWithObjectAbility = characterLocomotion.GetAbility<MoveWithObject>();
|
||||
if (m_MoveWithObjectAbility == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_MoveWithObjectAbility.Target = m_Transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the platform.
|
||||
/// </summary>
|
||||
private void FixedUpdate()
|
||||
{
|
||||
// Move towards the active position when the ability reference is not null. This will be set within OnTriggerEnter/Exit.
|
||||
m_Transform.position = Vector3.MoveTowards(m_Transform.position, (m_MoveWithObjectAbility != null ? m_ActivePosition : m_RestingPosition), m_MoveSpeed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An object has exited the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider that entered the trigger. May or may not be a character.</param>
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, 1 << LayerManager.Character) || m_MoveWithObjectAbility == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_MoveWithObjectAbility.Target = null;
|
||||
m_MoveWithObjectAbility = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e78c4b081a5326a4f9b1b2280b21fcff
|
||||
timeCreated: 1554810719
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,102 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Character;
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Teleports the character to the specified destination.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(BoxCollider))]
|
||||
public class Teleporter : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The location that the character will teleport to.")]
|
||||
[SerializeField] protected Transform m_Destination;
|
||||
[Tooltip("Should the character's animator be snapped when teleporting to the destination?")]
|
||||
[SerializeField] protected bool m_SnapAnimator;
|
||||
[Tooltip("The LayerMask of the character.")]
|
||||
[SerializeField] protected LayerMask m_LayerMask = 1 << LayerManager.Character;
|
||||
[Tooltip("The AudioClip that should play when the character is teleported.")]
|
||||
[SerializeField] protected AudioClip m_TeleportAudioClip;
|
||||
[Tooltip("The name of the state that should activate when the character teleports.")]
|
||||
[SerializeField] protected string m_StateName;
|
||||
#if UNITY_EDITOR
|
||||
[Tooltip("The color to draw the editor gizmo in (editor only).")]
|
||||
[SerializeField] protected Color m_GizmoColor = new Color(0, 0, 1, 0.3f);
|
||||
#endif
|
||||
|
||||
public Transform Destination { get { return m_Destination; } set { m_Destination = value; } }
|
||||
#if UNITY_EDITOR
|
||||
public Color GizmoColor { get { return m_GizmoColor; } set { m_GizmoColor = value; } }
|
||||
#endif
|
||||
|
||||
private AudioSource m_AudioSource;
|
||||
|
||||
private bool m_IgnoreCharacterEnter;
|
||||
|
||||
public bool IgnoreCharacterEnter { set { m_IgnoreCharacterEnter = true; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_AudioSource = GetComponent<AudioSource>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Teleport the character to the specified destination.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider that entered the trigger. May or may not be a character.</param>
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, m_LayerMask) || m_IgnoreCharacterEnter) {
|
||||
return;
|
||||
}
|
||||
|
||||
UltimateCharacterLocomotion characterLocomotion;
|
||||
if ((characterLocomotion = other.GetComponentInParent<UltimateCharacterLocomotion>()) != null) {
|
||||
// Do not allow teleportation if the Drive or Ride abilities are active.
|
||||
if (characterLocomotion.IsAbilityTypeActive<UltimateCharacterController.Character.Abilities.Drive>() ||
|
||||
characterLocomotion.IsAbilityTypeActive<UltimateCharacterController.Character.Abilities.Ride>()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var destinationTeleporter = m_Destination.GetComponentInParent<Teleporter>();
|
||||
if (destinationTeleporter != null) {
|
||||
destinationTeleporter.IgnoreCharacterEnter = true;
|
||||
}
|
||||
characterLocomotion.SetPositionAndRotation(m_Destination.position, m_Destination.rotation, m_SnapAnimator);
|
||||
|
||||
if (m_AudioSource != null && m_TeleportAudioClip != null) {
|
||||
m_AudioSource.clip = m_TeleportAudioClip;
|
||||
m_AudioSource.Play();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(m_StateName)) {
|
||||
StateSystem.StateManager.SetState(characterLocomotion.gameObject, m_StateName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An object has exited the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider that entered the trigger. May or may not be a character.</param>
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, m_LayerMask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_IgnoreCharacterEnter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6fbe57b61f6ad9459762bb36de41799
|
||||
timeCreated: 1510845725
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,206 +0,0 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.Demo.Objects
|
||||
{
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.Character;
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
|
||||
using Opsive.UltimateCharacterController.Networking;
|
||||
using Opsive.UltimateCharacterController.Networking.Game;
|
||||
#endif
|
||||
using Opsive.UltimateCharacterController.Objects;
|
||||
using Opsive.UltimateCharacterController.SurfaceSystem;
|
||||
using Opsive.UltimateCharacterController.Traits;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A simple turret which will fire a projectile towards the character. This turret is setup for the demo scene and will likely require modifications if used in other areas.
|
||||
/// </summary>
|
||||
public class Turret : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The object that rotates on the turret.")]
|
||||
[SerializeField] protected Transform m_TurretHead;
|
||||
[Tooltip("The speed at which the head rotates.")]
|
||||
[SerializeField] protected float m_RotationSpeed = 5;
|
||||
|
||||
[Tooltip("The location that the projectile should be fired.")]
|
||||
[SerializeField] protected Transform m_FireLocation;
|
||||
[Tooltip("The distance in which the turret can start firing.")]
|
||||
[SerializeField] protected float m_FireRange = 10;
|
||||
[Tooltip("The delay until the turret will fire again.")]
|
||||
[SerializeField] protected float m_FireDelay = 0.5f;
|
||||
|
||||
[Tooltip("The projectile that is fired.")]
|
||||
[SerializeField] protected GameObject m_Projectile;
|
||||
[Tooltip("The magnitude of the projectile velocity when fired. The direction is determined by the fire direction.")]
|
||||
[SerializeField] protected float m_VelocityMagnitude = 10;
|
||||
[Tooltip("A LayerMask of the layers that can be hit when fired at.")]
|
||||
[SerializeField] protected LayerMask m_ImpactLayers = ~(1 << LayerManager.IgnoreRaycast | 1 << LayerManager.TransparentFX | 1 << LayerManager.UI | 1 << LayerManager.Overlay);
|
||||
[Tooltip("The amount of damage to apply to the hit object.")]
|
||||
[SerializeField] protected float m_DamageAmount = 10;
|
||||
[Tooltip("How much force to apply to the hit object.")]
|
||||
[SerializeField] protected float m_ImpactForce = 0.05f;
|
||||
[Tooltip("The number of frames to add the force to.")]
|
||||
[SerializeField] protected int m_ImpactForceFrames = 1;
|
||||
[Tooltip("The Surface Impact triggered when the weapon hits an object.")]
|
||||
[SerializeField] protected SurfaceImpact m_SurfaceImpact;
|
||||
|
||||
[Tooltip("Optionally specify a muzzle flash that should appear when the turret is fired.")]
|
||||
[SerializeField] protected GameObject m_MuzzleFlash;
|
||||
[Tooltip("The location that the muzzle flash should spawn.")]
|
||||
[SerializeField] protected Transform m_MuzzleFlashLocation;
|
||||
|
||||
[Tooltip("Optionally specify an audio clip that should play when the turret is fired.")]
|
||||
[SerializeField] protected AudioClip m_FireAudioClip;
|
||||
|
||||
private GameObject m_GameObject;
|
||||
private Transform m_Transform;
|
||||
private AudioSource m_AudioSource;
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
|
||||
private INetworkInfo m_NetworkInfo;
|
||||
#endif
|
||||
|
||||
private Transform m_Target;
|
||||
private Health m_Health;
|
||||
private float m_LastFireTime;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_GameObject = gameObject;
|
||||
m_Transform = transform;
|
||||
m_AudioSource = GetComponent<AudioSource>();
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
|
||||
m_NetworkInfo = GetComponent<INetworkInfo>();
|
||||
#endif
|
||||
|
||||
// A turret head is required.
|
||||
if (m_TurretHead == null) {
|
||||
m_TurretHead = m_Transform;
|
||||
}
|
||||
}
|
||||
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
|
||||
/// <summary>
|
||||
/// Determine if the object should be enabled on the network.
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
if (m_NetworkInfo != null && !m_NetworkInfo.IsLocalPlayer()) {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The turret has been enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
m_LastFireTime = Time.time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the turret head and attacks if the character is within range.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
if (m_Target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RotateTowardsTarget();
|
||||
CheckForAttack();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keep facing the target so the turret can fire at any time.
|
||||
/// </summary>
|
||||
public void RotateTowardsTarget()
|
||||
{
|
||||
var targetRotation = Quaternion.Euler(0, Quaternion.LookRotation(m_TurretHead.position - m_Target.position).eulerAngles.y, 0);
|
||||
m_TurretHead.rotation = Quaternion.Slerp(m_TurretHead.rotation, targetRotation, m_RotationSpeed * Time.deltaTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the turret can attack.
|
||||
/// </summary>
|
||||
public void CheckForAttack()
|
||||
{
|
||||
// The turret can attack if it hasn't fired recently and the target is in front of the turret.
|
||||
if (m_LastFireTime + m_FireDelay < Time.time && (m_Transform.position - m_Target.position).magnitude < m_FireRange && (m_Health == null || m_Health.Value > 0)) {
|
||||
Fire();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 = ObjectPool.Instantiate(m_Projectile, m_FireLocation.position, m_Transform.rotation).GetCachedComponent<Projectile>();
|
||||
projectile.Initialize(m_FireLocation.forward * m_VelocityMagnitude, Vector3.zero, 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 = ObjectPool.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>
|
||||
/// An object has entered the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The object that entered the trigger.</param>
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (m_Target != null || !MathUtility.InLayerMask(other.gameObject.layer, 1 << LayerManager.Character)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var characterLocomotion = other.GetComponentInParent<UltimateCharacterLocomotion>();
|
||||
if (characterLocomotion == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Target = characterLocomotion.transform;
|
||||
m_Health = characterLocomotion.GetComponent<Health>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An object has exited the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider that exited the trigger.</param>
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (other.gameObject != m_Target) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Target = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14f6d55780b9f914c8d4c40bb2fbf030
|
||||
timeCreated: 1525258500
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user