This commit is contained in:
2026-06-09 09:18:17 +07:00
parent 3578a2750c
commit 71a096556a
5777 changed files with 6675 additions and 13 deletions

View File

@@ -1,68 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Items.Actions.Magic.BeginEndActions
{
using Opsive.UltimateCharacterController.StateSystem;
using Opsive.UltimateCharacterController.Utility;
using UnityEngine;
/// <summary>
/// Start End Actions will perform an action when the Magic Item use is beginning or is ending.
/// </summary>
[System.Serializable]
[UnityEngine.Scripting.Preserve]
[AllowDuplicateTypes]
public abstract class BeginEndAction : StateObject
{
protected MagicItem m_MagicItem;
protected bool m_BeginAction;
protected int m_Index;
/// <summary>
/// Initializes the BeginEndAction.
/// </summary>
/// <param name="character">The character GameObject.</param>
/// <param name="magicItem">The MagicItem that the BeginEndAction belongs to.</param>
/// <param name="startAction">True if the action is a begin action.</param>
/// <param name="index">The index of the BeginEndAction.</param>
public virtual void Initialize(GameObject character, MagicItem magicItem, bool beginAction, int index)
{
base.Initialize(character);
m_MagicItem = magicItem;
m_BeginAction = beginAction;
m_Index = index;
}
/// <summary>
/// The action has started.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public virtual void Start(Transform origin) { }
/// <summary>
/// Updates the action.
/// </summary>
public virtual void Update() { }
/// <summary>
/// The action has stopped.
/// </summary>
public virtual void Stop() { }
/// <summary>
/// The character has changed perspectives.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public virtual void OnChangePerspectives(Transform origin) { }
/// <summary>
/// The action has been destroyed.
/// </summary>
public virtual void OnDestroy() { }
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 80d0573a0625f4c48bf32d094b518ef5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,257 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Items.Actions.Magic.BeginEndActions
{
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.Shared.Utility;
using Opsive.UltimateCharacterController.Character.Identifiers;
using Opsive.UltimateCharacterController.Utility;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Fades the materials on the character.
/// </summary>
[System.Serializable]
public class FadeMaterials : BeginEndAction
{
[Tooltip("The name of the material property that should be faded.")]
[SerializeField] protected string m_ColorPropertyName = "_Color";
[Tooltip("The alpha color that the materials should fade to.")]
[SerializeField] protected float m_TargetAlpha = 0;
[Tooltip("The speed of the fade.")]
[SerializeField] protected float m_FadeSpeed = 0.02f;
[Tooltip("Should the fade be reverted when the action stops?")]
[SerializeField] protected bool m_RevertFadeOnStop;
public string ColorPropertyName { get { return m_ColorPropertyName; } set { m_ColorPropertyName = value; } }
public float TargetAlpha { get { return m_TargetAlpha; } set { m_TargetAlpha = value; } }
public float FadeSpeed { get { return m_FadeSpeed; } set { m_FadeSpeed = value; } }
private int m_ColorID;
private GameObject m_Character;
private bool m_Active;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
private ScheduledEventBase m_UpdateEvent;
#endif
private FadeMaterials m_BeginFadeMaterials;
private List<Material> m_Materials = new List<Material>();
private HashSet<Material> m_ActiveMaterials = new HashSet<Material>();
private Dictionary<Material, OriginalMaterialValue> m_OriginalMaterialValuesMap = new Dictionary<Material, OriginalMaterialValue>();
public List<Material> Materials { get { return m_Materials; } }
public HashSet<Material> ActiveMaterials { get { return m_ActiveMaterials; } }
public Dictionary<Material, OriginalMaterialValue> OriginalMaterialValuesMap { get { return m_OriginalMaterialValuesMap; } }
/// <summary>
/// Initializes the BeginEndAction.
/// </summary>
/// <param name="character">The character GameObject.</param>
/// <param name="magicItem">The MagicItem that the BeginEndAction belongs to.</param>
/// <param name="beginAction">True if the action is a begin action.</param>
/// <param name="index">The index of the BeginEndAction.</param>
public override void Initialize(GameObject character, MagicItem magicItem, bool beginAction, int index)
{
base.Initialize(character, magicItem, beginAction, index);
m_Character = character;
EventHandler.RegisterEvent<bool>(m_Character, "OnCharacterChangePerspectives", OnChangePerspectives);
}
/// <summary>
/// The action has started.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public override void Start(Transform origin)
{
// Initialize any starting values after all of the actions have been deserialized.
if (m_ColorID == 0) {
m_ColorID = Shader.PropertyToID(m_ColorPropertyName);
if (!m_BeginAction && m_MagicItem.BeginActions != null) {
for (int i = 0; i < m_MagicItem.BeginActions.Length; ++i) {
if (m_MagicItem.BeginActions[i] is FadeMaterials) {
m_BeginFadeMaterials = m_MagicItem.BeginActions[i] as FadeMaterials;
break;
}
}
}
}
// The Object Fader should reset.
EventHandler.ExecuteEvent(m_Character, "OnCharacterIndependentFade", true, true);
if (m_BeginFadeMaterials == null) {
// Return the previous objects.
if (m_OriginalMaterialValuesMap.Count > 0) {
for (int i = 0; i < m_Materials.Count; ++i) {
GenericObjectPool.Return(m_OriginalMaterialValuesMap[m_Materials[i]]);
m_OriginalMaterialValuesMap.Remove(m_Materials[i]);
}
}
m_Materials.Clear();
m_ActiveMaterials.Clear();
EnableRendererFade();
} else {
m_Materials = m_BeginFadeMaterials.Materials;
m_ActiveMaterials = m_BeginFadeMaterials.ActiveMaterials;
m_OriginalMaterialValuesMap = m_BeginFadeMaterials.OriginalMaterialValuesMap;
}
m_Active = true;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
// Update isn't called automatically for the remote players.
if (m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer()) {
m_UpdateEvent = Scheduler.Schedule(0.001f, Update);
}
#endif
}
/// <summary>
/// Enables fading on the renderers.
/// </summary>
private void EnableRendererFade()
{
// Fade all of the active renderers.
var renderers = m_Character.GetComponentsInChildren<Renderer>(false);
for (int i = 0; i < renderers.Length; ++i) {
// The fade can be ignored.
if (renderers[i].gameObject.GetCachedComponent<IgnoreFadeIdentifier>() != null) {
continue;
}
var materials = renderers[i].materials;
for (int j = 0; j < materials.Length; ++j) {
var material = materials[j];
if (m_ActiveMaterials.Contains(material) || !material.HasProperty(m_ColorID)) {
continue;
}
m_Materials.Add(material);
m_ActiveMaterials.Add(material);
// Cache the original values so they can be reverted.
var originalMaterialValues = GenericObjectPool.Get<OriginalMaterialValue>();
originalMaterialValues.Initialize(material, m_ColorID, material.HasProperty(OriginalMaterialValue.ModeID));
m_OriginalMaterialValuesMap.Add(material, originalMaterialValues);
// The material should be able to fade.
material.SetFloat(OriginalMaterialValue.ModeID, 2);
material.SetInt(OriginalMaterialValue.SrcBlendID, (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt(OriginalMaterialValue.DstBlendID, (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.EnableKeyword(OriginalMaterialValue.AlphaBlendString);
material.renderQueue = 3000;
// If the action is already active then the material is being faded when the perspective is switching. Set the alpha to the
// same alpha value as the rest of the materials.
if (m_Active) {
var color = material.GetColor(m_ColorID);
color.a = m_Materials[0].GetColor(m_ColorID).a;
material.SetColor(m_ColorID, color);
}
}
}
}
/// <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 = Scheduler.Schedule(0.001f, Update);
}
#endif
m_Active = active;
}
/// <summary>
/// The action has stopped.
/// </summary>
public override void Stop()
{
if (!m_Active) {
return;
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_MagicItem.NetworkInfo != null && !m_MagicItem.NetworkInfo.IsLocalPlayer()) {
Scheduler.Cancel(m_UpdateEvent);
}
#endif
EventHandler.ExecuteEvent(m_Character, "OnCharacterIndependentFade", false, false);
m_Active = false;
if (!m_RevertFadeOnStop) {
return;
}
// Revert the values back to the original values.
var fade = m_BeginFadeMaterials != null ? m_BeginFadeMaterials : this;
var originalMaterialValues = fade.OriginalMaterialValuesMap;
var materials = fade.Materials;
for (int i = 0; i < materials.Count; ++i) {
if (!originalMaterialValues.TryGetValue(materials[i], out var originalMaterialValue)) {
continue;
}
// Revert the material back to the starting value.
materials[i].SetColor(m_ColorID, originalMaterialValue.Color);
if (originalMaterialValue.ContainsMode) {
materials[i].SetFloat(OriginalMaterialValue.ModeID, originalMaterialValue.Mode);
materials[i].SetInt(OriginalMaterialValue.SrcBlendID, originalMaterialValue.SrcBlend);
materials[i].SetInt(OriginalMaterialValue.DstBlendID, originalMaterialValue.DstBlend);
}
if (!originalMaterialValue.AlphaBlend) {
materials[i].DisableKeyword(OriginalMaterialValue.AlphaBlendString);
}
materials[i].renderQueue = originalMaterialValue.RenderQueue;
}
}
/// <summary>
/// The character perspective between first and third person has changed.
/// </summary>
/// <param name="firstPersonPerspective">Is the character in a first person perspective?</param>
private void OnChangePerspectives(bool firstPersonPerspective)
{
if (firstPersonPerspective || !m_Active) {
return;
}
EnableRendererFade();
}
/// <summary>
/// The action has been destroyed.
/// </summary>
public override void OnDestroy()
{
base.OnDestroy();
EventHandler.UnregisterEvent<bool>(m_Character, "OnCharacterChangePerspectives", OnChangePerspectives);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 43b4b58ee873cec4db5071677895216a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,84 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Items.Actions.Magic.BeginEndActions
{
using Opsive.UltimateCharacterController.Audio;
using UnityEngine;
/// <summary>
/// Plays an audio clip.
/// </summary>
[System.Serializable]
public class PlayAudioClip : BeginEndAction
{
[Tooltip("The AudioClip that should be played. A random AudioClip will be selected.")]
[SerializeField] protected AudioClip[] m_AudioClips;
[Tooltip("Plays the AudioClip at the origin. If the value is false the character position will be used.")]
[SerializeField] protected bool m_PlayAtOrigin = true;
[Tooltip("Should the AudioClip loop?")]
[SerializeField] protected bool m_Loop;
public AudioClip[] AudioClips { get { return m_AudioClips; } set { m_AudioClips = value; } }
public bool PlayAtOrigin { get { return m_PlayAtOrigin; } set { m_PlayAtOrigin = value; } }
public bool Loop { get { return m_Loop; } set { m_Loop = value; } }
private Transform m_CharacterTransform;
private AudioSource m_AudioSource;
/// <summary>
/// Initializes the action.
/// </summary>
/// <param name="character">The character GameObject.</param>
/// <param name="magicItem">The MagicItem that the StartAction belongs to.</param>
/// <param name="beginAction">True if the action is a starting action.</param>
/// <param name="index">The index of the BeginEndAction.</param>
public override void Initialize(GameObject character, MagicItem magicItem, bool beginAction, int index)
{
base.Initialize(character, magicItem, beginAction, index);
m_CharacterTransform = character.transform;
}
/// <summary>
/// The action has started.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public override void Start(Transform origin)
{
if (m_AudioSource != 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_CharacterTransform.position);
if (m_AudioSource != null) {
m_AudioSource.loop = m_Loop;
}
}
/// <summary>
/// The action has stopped.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public override void Stop()
{
if (m_AudioSource != null) {
m_AudioSource.Stop();
m_AudioSource = null;
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c82ab1d5aa009204581e2cb719c03b55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,109 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Items.Actions.Magic.BeginEndActions
{
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Utility;
using UnityEngine;
/// <summary>
/// Spawns a particle.
/// </summary>
[System.Serializable]
public class SpawnParticle : BeginEndAction
{
[Tooltip("The particle prefab that should be spawned.")]
[SerializeField] protected GameObject m_ParticlePrefab;
[Tooltip("The positional offset that the particle should be spawned.")]
[SerializeField] protected Vector3 m_PositionOffset;
[Tooltip("The rotational offset that the particle should be spawned.")]
[SerializeField] protected Vector3 m_RotationOffset;
[Tooltip("Should the particle be parented to the origin?")]
[SerializeField] protected bool m_ParentToOrigin;
public GameObject ParticlePrefab { get { return m_ParticlePrefab; } set { m_ParticlePrefab = value; } }
public Vector3 PositionOffset { get { return m_PositionOffset; } set { m_PositionOffset = value; } }
public Vector3 RotationOffset { get { return m_RotationOffset; } set { m_RotationOffset = value; } }
public bool ParentToOrigin { get { return m_ParentToOrigin; } set { m_ParentToOrigin = value; } }
private Transform m_Transform;
private Transform m_SpawnedTransform;
/// <summary>
/// Initializes the BeginEndAction.
/// </summary>
/// <param name="character">The character GameObject.</param>
/// <param name="magicItem">The MagicItem that the BeginEndAction belongs to.</param>
/// <param name="startAction">True if the action is a begin action.</param>
/// <param name="index">The index of the BeginEndAction.</param>
public override void Initialize(GameObject character, MagicItem magicItem, bool beginAction, int index)
{
base.Initialize(character, magicItem, beginAction, index);
m_Transform = character.transform;
}
/// <summary>
/// The action has started.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public override void Start(Transform origin)
{
Spawn(origin);
}
/// <summary>
/// The action has stopped.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public override void Stop()
{
m_SpawnedTransform = null;
}
/// <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 = ObjectPool.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>
/// The character has changed perspectives.
/// </summary>
/// <param name="origin">The location that the cast originates from.</param>
public override void OnChangePerspectives(Transform origin)
{
if (m_SpawnedTransform == null || m_SpawnedTransform.parent == origin) {
return;
}
var localRotation = m_SpawnedTransform.localRotation;
var localScale = m_SpawnedTransform.localScale;
m_SpawnedTransform.parent = origin;
m_SpawnedTransform.position = MathUtility.TransformPoint(origin.position, m_Transform.rotation, m_PositionOffset);
m_SpawnedTransform.localRotation = localRotation;
m_SpawnedTransform.localScale = localScale;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 374cc4f1e138cd3499afa36d5add30cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: