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,327 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.SurfaceSystem
{
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Game;
using Opsive.UltimateCharacterController.Utility;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// The DecalManager is responsible for managing the spawned decals. The decals can be capped at a limit to prevent too many from being
/// spawned. These decals can then slowly be faded (weathered) for a smooth transition rather than the decal just popping out of existance.
/// </summary>
public class DecalManager : MonoBehaviour
{
private static DecalManager s_Instance;
private static DecalManager Instance
{
get
{
if (!s_Initialized) {
s_Instance = new GameObject("Decal Manager").AddComponent<DecalManager>();
s_Initialized = true;
}
return s_Instance;
}
}
private static bool s_Initialized;
[Tooltip("The maximum number of decals.")]
[SerializeField] protected int m_DecalLimit = 100;
[Tooltip("The number of decals which should slowly fade after the decal limit has been reached.")]
[SerializeField] protected int m_WeatheredDecalLimit = 20;
[Tooltip("The speed that the decals should fadeout after they have been removed from the weathered array.")]
[SerializeField] protected int m_RemoveFadeoutSpeed = 10;
public int DecalLimit { get { return m_DecalLimit; } set { m_DecalLimit = value; } }
public int WeatheredDecalLimit { get { return m_WeatheredDecalLimit; } set { m_WeatheredDecalLimit = value; } }
public int RemoveFadeoutSpeed { get { return m_RemoveFadeoutSpeed; } set { m_RemoveFadeoutSpeed = value; } }
private List<GameObject> m_Decals = new List<GameObject>();
private List<Renderer> m_WeatheredDecals = new List<Renderer>();
private List<Renderer> m_DecalsToFade = new List<Renderer>();
private Dictionary<GameObject, Renderer> m_DecalRendererMap = new Dictionary<GameObject, Renderer>();
private Dictionary<GameObject, Mesh> m_DecalMeshMap = new Dictionary<GameObject, Mesh>();
/// <summary>
/// The object has been enabled.
/// </summary>
private void OnEnable()
{
// The object may have been enabled outside of the scene unloading.
if (s_Instance == null) {
s_Instance = this;
s_Initialized = true;
SceneManager.sceneUnloaded -= SceneUnloaded;
}
}
/// <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 decal to spawn.</param>
/// <param name="scale">The scale of the decal to spawn.</param>
/// <param name="allowedEdgeOverlap">How close to the edge the decal is allowed to spawn.</param>
public static void Spawn(GameObject original, RaycastHit hit, float scale, float allowedEdgeOverlap)
{
Instance.SpawnInternal(original, hit, scale, allowedEdgeOverlap);
}
/// <summary>
/// Internal method which 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 decal to spawn.</param>
/// <param name="scale">The scale of the decal to spawn.</param>
/// <param name="allowedEdgeOverlap">How close to the edge the decal is allowed to spawn.</param>
private void SpawnInternal(GameObject original, RaycastHit hit, float scale, float allowedEdgeOverlap)
{
SpawnDecal(original, hit, Quaternion.LookRotation(hit.normal) * Quaternion.AngleAxis(Random.Range(0, 360), Vector3.forward), scale, allowedEdgeOverlap);
}
/// <summary>
/// Instantiates a new footprint.
/// </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="scale">The scale of the decal to spawn.</param>
/// <param name="allowedEdgeOverlap">How close to the edge the footprint is allowed to spawn.</param>
/// <param name="footprintDirection">The direction that the footprint decal should face.</param>
/// <param name="flipFootprint">Should the footprint decal be flipped?</param>
public static void SpawnFootprint(GameObject original, RaycastHit hit, float scale, float allowedEdgeOverlap, Vector3 footprintDirection, bool flipFootprint)
{
Instance.SpawnFootprintInternal(original, hit, scale, allowedEdgeOverlap, footprintDirection, flipFootprint);
}
/// <summary>
/// Internal method which instantiates a new footprint.
/// </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="scale">The scale of the decal to spawn.</param>
/// <param name="allowedEdgeOverlap">How close to the edge the footprint is allowed to spawn.</param>
/// <param name="footprintDirection">The direction that the footprint decal should face.</param>
/// <param name="flipFootprint">Should the footprint decal be flipped?</param>
private void SpawnFootprintInternal(GameObject original, RaycastHit hit, float scale, float allowedEdgeOverlap, Vector3 footprintDirection, bool flipFootprint)
{
var decal = SpawnDecal(original, hit, Quaternion.LookRotation(hit.normal, footprintDirection), scale, allowedEdgeOverlap);
// Changing the local x axis will flip the footprint.
if (decal != null && flipFootprint) {
var localScale = decal.transform.localScale;
localScale.x *= -1;
decal.transform.localScale = localScale;
}
}
/// <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 = ObjectPool.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 = Vector3.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)) {
ObjectPool.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)) {
ObjectPool.Destroy(decal);
return null;
}
}
// The decal can be added.
Add(decal);
return decal;
}
/// <summary>
/// Stores the decal's mesh and renderer.
/// </summary>
/// <param name="decal">The decal to store the mesh and renderer of.</param>
/// <returns>True if the mesh and renderer were able to be cached.</returns>
private bool CacheMeshAndRenderer(GameObject decal)
{
Renderer renderer;
if (!m_DecalRendererMap.TryGetValue(decal, out renderer)) {
var meshFilter = decal.GetComponent<MeshFilter>();
if (meshFilter == null) {
return false;
}
if (meshFilter.mesh == null) {
return false;
}
renderer = decal.GetComponent<Renderer>();
if (renderer == null) {
return false;
}
if (renderer.material == null) {
return false;
}
// Cache the decal renderer and mesh.
m_DecalRendererMap.Add(decal, renderer);
m_DecalMeshMap.Add(decal, meshFilter.mesh);
}
// The decal should start opaque.
var color = renderer.material.color;
color.a = 1;
renderer.material.color = color;
return true;
}
/// <summary>
/// Check all four corners of the decal for surface contact.
/// </summary>
/// <param name="decal">The decal to check the corners of.</param>
/// <param name="allowedEdgeOverlap">How close to the edge the decal is allowed to spawn.</param>
/// <returns>True if all four corners are flush against a surface.</returns>
private bool DoQuadTest(GameObject decal, float allowedEdgeOverlap)
{
Mesh mesh;
if (!m_DecalMeshMap.TryGetValue(decal, out mesh)) {
return false;
}
RaycastHit hit;
for (int i = 0; i < 4; i++) {
// The decal isn't hitting anything if the raycast returns false.
if (!Physics.Raycast(decal.transform.TransformPoint(mesh.vertices[i] * (1 - (allowedEdgeOverlap * 2))) + (decal.transform.forward * 0.1f),
-decal.transform.forward, out hit, 0.2f, ~((1 << LayerManager.TransparentFX) | (1 << LayerManager.IgnoreRaycast) |
(1 << LayerManager.VisualEffect) | (1 << LayerManager.Water)), QueryTriggerInteraction.Ignore)) {
return false;
}
}
return true;
}
/// <summary>
/// Adds the decal to the active decal stack.
/// </summary>
/// <param name="decal">The decal to add.</param>
private void Add(GameObject decal)
{
m_Decals.Add(decal);
// If the total decal count is greater than the specified limit then the oldest decal should start to be weathered.
if (m_Decals.Count >= m_DecalLimit) {
var oldestDecalRenderer = m_DecalRendererMap[m_Decals[0]];
m_WeatheredDecals.Add(oldestDecalRenderer);
m_Decals.RemoveAt(0);
WeatherDecals();
}
}
/// <summary>
/// Slowly fade out the oldest decal in the weathered list.
/// </summary>
private void WeatherDecals()
{
// As each decal is added to the weathered list it should slowly fade out.
for (int i = 0; i < m_WeatheredDecals.Count; ++i) {
if (m_WeatheredDecals[i] == null) {
m_WeatheredDecals.RemoveAt(i);
continue;
}
var color = m_WeatheredDecals[i].material.color;
color.a = Mathf.Clamp01(color.a - (1 / (float)m_WeatheredDecalLimit));
m_WeatheredDecals[i].material.color = color;
}
// Remove the oldest weathered decal if the limit is reached. This decal will be added to the fade list.
if (m_WeatheredDecals.Count >= m_WeatheredDecalLimit) {
m_DecalsToFade.Add(m_WeatheredDecals[0]);
m_WeatheredDecals.RemoveAt(0);
enabled = true;
}
}
/// <summary>
/// Fade out the decals in the decals to fade list.
/// </summary>
private void Update()
{
for (int i = m_DecalsToFade.Count - 1; i >= 0; --i) {
if (m_DecalsToFade[i] == null) {
m_DecalsToFade.RemoveAt(i);
continue;
}
var color = m_DecalsToFade[i].material.color;
color.a = Mathf.Lerp(color.a, 0, Time.deltaTime * m_RemoveFadeoutSpeed);
// The decal can be removed from the list when it is completely faded out.
if (color.a == 0) {
ObjectPool.Destroy(m_DecalsToFade[i].gameObject);
m_DecalsToFade.RemoveAt(i);
} else {
m_DecalsToFade[i].material.color = color;
}
}
// The component can be disabled when there are no decals within the list.
if (m_DecalsToFade.Count == 0) {
enabled = false;
}
}
/// <summary>
/// Reset the initialized variable when the scene is no longer loaded.
/// </summary>
/// <param name="scene">The scene that was unloaded.</param>
private void SceneUnloaded(Scene scene)
{
s_Initialized = false;
s_Instance = null;
SceneManager.sceneUnloaded -= SceneUnloaded;
}
/// <summary>
/// The object has been disabled.
/// </summary>
private void OnDisable()
{
SceneManager.sceneUnloaded += SceneUnloaded;
}
#if UNITY_2019_3_OR_NEWER
/// <summary>
/// Reset the static variables for domain reloading.
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void DomainReset()
{
s_Initialized = false;
s_Instance = null;
}
#endif
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 8b17e11b4e85729449b773c74f06daef
timeCreated: 1508769295
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,243 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.SurfaceSystem
{
using Opsive.UltimateCharacterController.Audio;
using Opsive.UltimateCharacterController.StateSystem;
using Opsive.UltimateCharacterController.Utility;
using UnityEngine;
/// <summary>
/// Specifies a recipe for effects that can be spawned in response to a certain type of collision. This collision might occur when
/// bullets hit a wall, a character places a footprint, or the character falls to the ground.
/// </summary>
public class SurfaceEffect : ScriptableObject
{
[Tooltip("Objects that should be spawned during a collision.")]
[SerializeField] protected ObjectSpawnInfo[] m_SpawnedObjects;
[Tooltip("An array of decals that can be spawned. A single decal will be randomlly chosen when the SurfaceEffect should spawn.")]
[SerializeField] protected GameObject[] m_Decals;
[Tooltip("The minimum scale of the decal.")]
[SerializeField] protected float m_MinDecalScale = 1;
[Tooltip("The maximum scale of the decal.")]
[SerializeField] protected float m_MaxDecalScale = 1;
[Tooltip("How close to the edge the decal is allowed to spawn. A value of 0 requires the full quad is required to sit on the background surface.")]
[Range(0, 0.5f)] [SerializeField] protected float m_AllowedDecalEdgeOverlap = 0.25f;
[Tooltip("The AudioClips that can be triggered from a collision.")]
[SerializeField] protected AudioClip[] m_AudioClips;
[Tooltip("The minimum volume of the AudioClip.")]
[SerializeField] protected float m_MinAudioVolume = 1;
[Tooltip("The maximum volume of the AudioClip.")]
[SerializeField] protected float m_MaxAudioVolume = 1;
[Tooltip("The minimum pitch of the AudioClip.")]
[SerializeField] protected float m_MinAudioPitch = 1;
[Tooltip("The maximum pitch of the AudioClip.")]
[SerializeField] protected float m_MaxAudioPitch = 1;
[Tooltip("Should a maximum of one clip be played per frame? This prevents too many sounds from playing at once.")]
[SerializeField] protected bool m_OneClipPerFrame;
[Tooltip("Should the AudioClip be randomly selected? If false the clips will be played sequentially.")]
[SerializeField] protected bool m_RandomClipSelection = true;
[Tooltip("The name of the state that should be activated upon impact.")]
[SerializeField] protected string m_StateName;
[Tooltip("The number of seconds until the specified state is disabled. A value of -1 will require the state to be disabled manually.")]
[SerializeField] protected float m_StateDisableTimer = 10;
public ObjectSpawnInfo[] SpawnedObjects { get { return m_SpawnedObjects; } set { m_SpawnedObjects = value; } }
public GameObject[] Decals { get { return m_Decals; } set { m_Decals = value; } }
public float MinDecalScale { get { return m_MinDecalScale; } set { m_MinDecalScale = value; } }
public float MaxDecalScale { get { return m_MaxDecalScale; } set { m_MaxDecalScale = value; } }
public float AllowedDecalEdgeOverlap { get { return m_AllowedDecalEdgeOverlap; } set { m_AllowedDecalEdgeOverlap = value; } }
public AudioClip[] AudioClips { get { return m_AudioClips; } set { m_AudioClips = value; } }
public float MinAudioVolume { get { return m_MinAudioVolume; } set { m_MinAudioVolume = value; } }
public float MaxAudioVolume { get { return m_MaxAudioVolume; } set { m_MaxAudioVolume = value; } }
public float MinAudioPitch { get { return m_MinAudioPitch; } set { m_MinAudioPitch = value; } }
public float MaxAudioPitch { get { return m_MaxAudioPitch; } set { m_MaxAudioPitch = value; } }
public bool OneClipPerFrame { get { return m_OneClipPerFrame; } set { m_OneClipPerFrame = value; } }
public bool RandomClipSelection { get { return m_RandomClipSelection; } set { m_RandomClipSelection = value; } }
public string StateName { get { return m_StateName; } set { m_StateName = value; } }
public float StateDisableTimer { get { return m_StateDisableTimer; } set { m_StateDisableTimer = value; } }
private GameObject m_LastSpawnedDecal;
private AudioClip m_LastPlayedAudioClip;
private int m_LastPlayedAudioClipFrame;
private int m_AudioClipIndex;
/// <summary>
/// Spawns the surface objects and decals.
/// </summary>
/// <param name="hit">The RaycastHit which caused the collision.</param>
/// <param name="gravityDirection">The normalized direction of the character's gravity.</param>
/// <param name="timeScale">The timescale of the originator.</param>
/// <param name="originator">The object which spawned the effect.</param>
/// <param name="spawnDecals">Should the decals be spawned? Not all surfaces allow for decals.</param>
public void Spawn(RaycastHit hit, Vector3 gravityDirection, float timeScale, GameObject originator, bool spawnDecals)
{
SpawnObjects(hit, gravityDirection);
PlayAudioClip(hit, timeScale, null);
SetState(hit);
// Return early if the SurfaceType doesn't allow decals.
if (!spawnDecals) {
return;
}
SpawnDecal(hit);
}
/// <summary>
/// Instantiates the Spawned Objects.
/// </summary>
/// <param name="hit">The RaycastHit which caused the collision.</param>
/// <param name="gravityDirection">The normalized direction of the character's gravity.</param>
private void SpawnObjects(RaycastHit hit, Vector3 gravityDirection)
{
for (int i = 0; i < m_SpawnedObjects.Length; ++i) {
if (m_SpawnedObjects[i] == null) {
continue;
}
m_SpawnedObjects[i].Instantiate(hit.point, hit.normal, gravityDirection);
}
}
/// <summary>
/// Instantiates a decal.
/// </summary>
/// <param name="hit">The RaycastHit which caused the collision.</param>
private void SpawnDecal(RaycastHit hit)
{
var decal = GetDecal();
// The last spawned decal should be remembered so no two decals are spawned immediately after one another if multiple decals can be spawned.
m_LastSpawnedDecal = decal;
DecalManager.Spawn(decal, hit, Random.Range(m_MinDecalScale, m_MaxDecalScale), m_AllowedDecalEdgeOverlap);
}
/// <summary>
/// Returns a random decal from the decals array.
/// </summary>
/// <returns>A random decal from the decals array.</returns>
private GameObject GetDecal()
{
if (m_Decals.Length == 0) {
return null;
}
// A random decal should be chosen from the array.
var decal = m_Decals[Random.Range(0, m_Decals.Length)];
if (decal == null) {
return null;
}
// If there are multiple decals available then the same decal shouldn't spawn twice in a row.
while (m_Decals.Length > 1 && decal == m_LastSpawnedDecal) {
decal = m_Decals[Random.Range(0, m_Decals.Length)];
if (decal == null) {
return null;
}
}
return decal;
}
/// <summary>
/// A footprint and any related effects should be spawned at the hit point.
/// </summary>
/// <param name="hit">The RaycastHit which caused the collision.</param>
/// <param name="gravityDirection">The normalized direction of the character's gravity.</param>
/// <param name="timeScale">The timescale of the originator.</param>
/// <param name="originator">The object which spawned the effect.</param>
/// <param name="spawnDecals">Should the decals be spawned? Not all surfaces allow for decals.</param>
/// <param name="footprintDirection">The direction that the footprint decal should face.</param>
/// <param name="flipFootprint">Should the footprint decal be flipped?</param>
public void SpawnFootprint(RaycastHit hit, Vector3 gravityDirection, float timeScale, GameObject originator, bool spawnDecals, Vector3 footprintDirection, bool flipFootprint)
{
SpawnObjects(hit, gravityDirection);
PlayAudioClip(hit, timeScale, originator);
SetState(hit);
// Return early if the SurfaceType doesn't allow decals.
if (!spawnDecals) {
return;
}
// The DecalManager will do the footprint spawn.
DecalManager.SpawnFootprint(GetDecal(), hit, Random.Range(m_MinDecalScale, m_MaxDecalScale), m_AllowedDecalEdgeOverlap, footprintDirection, flipFootprint);
}
/// <summary>
/// Plays an AudioClip on the specified GameObject.
/// </summary>
/// <param name="hit">The RaycastHit which caused the collision.</param>
/// <param name="timeScale">The timescale of the originator.</param>
/// <param name="originator">The object which should play the audio clip.</param>
private void PlayAudioClip(RaycastHit hit, float timeScale, GameObject originator)
{
// No clips can be played if there are no clips in the array.
if (m_AudioClips == null || m_AudioClips.Length == 0) {
return;
}
// Don't play too many clips at once.
if (m_OneClipPerFrame && m_LastPlayedAudioClipFrame == Time.frameCount) {
return;
}
// Get the AudioClip.
AudioClip audioClip;
if (m_RandomClipSelection) {
audioClip = m_AudioClips[Random.Range(0, m_AudioClips.Length)];
} else {
audioClip = m_AudioClips[m_AudioClipIndex];
m_AudioClipIndex = (m_AudioClipIndex + 1) % m_AudioClips.Length;
}
// If there are multiple clips available then the same clip shouldn't be played twice in a row.
while (m_AudioClips.Length > 1 && audioClip == m_LastPlayedAudioClip) {
audioClip = m_AudioClips[Random.Range(0, m_AudioClips.Length)];
if (audioClip == null) {
return;
}
}
// Play the clip.
var pitch = Random.Range(m_MinAudioPitch, m_MaxAudioPitch) * Time.timeScale * timeScale;
if (originator != null) {
AudioManager.Play(originator, audioClip, pitch);
} else {
var volume = Random.Range(m_MinAudioVolume, m_MaxAudioVolume);
AudioManager.PlayAtPosition(audioClip, hit.point, volume, pitch);
}
// Update the state.
m_LastPlayedAudioClip = audioClip;
m_LastPlayedAudioClipFrame = Time.frameCount;
}
/// <summary>
/// Sets the specified state on the hit object.
/// </summary>
/// <param name="hit">The RaycastHit which caused the collision.</param>
private void SetState(RaycastHit hit)
{
if (string.IsNullOrEmpty(m_StateName)) {
return;
}
var hitGameObject = hit.transform.gameObject;
StateManager.SetState(hitGameObject, m_StateName, true);
// If the timer isn't -1 then the state should be disabled after a specified amount of time. If it is -1 then the state
// will have to be disabled manually.
if (m_StateDisableTimer != -1) {
StateManager.DeactivateStateTimer(hitGameObject, m_StateName, m_StateDisableTimer);
}
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 1c9437dfa59d0164c89d59c14938f889
timeCreated: 1508164996
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: c596edb1305969e4c9bf7d24926cd658, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,24 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.SurfaceSystem
{
using UnityEngine;
/// <summary>
/// The SurfaceIdentifier can be added to GameObjects and identifies the type of surface the object belongs to.
/// </summary>
public class SurfaceIdentifier : MonoBehaviour
{
[Tooltip("The SurfaceType of the object.")]
[SerializeField] protected SurfaceType m_SurfaceType;
[Tooltip("Are decals allowed on this object?")]
[SerializeField] protected bool m_AllowDecals = true;
public SurfaceType SurfaceType { get { return m_SurfaceType; } }
public bool AllowDecals { get { return m_AllowDecals; } }
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: c6e458a25b435dd4086faf6dce3b39e6
timeCreated: 1508165009
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,18 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.SurfaceSystem
{
using UnityEngine;
/// <summary>
/// The SurfaceImpact is used to distinguish between different types of collisions for surface effects.
/// </summary>
public class SurfaceImpact : ScriptableObject
{
// Intentionally left blank.
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 8292fa0419937544a9bf8cfbdfc34954
timeCreated: 1508168240
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 3061bd671d9c87947bb5b99a48ab7e1b, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,16 +0,0 @@
fileFormatVersion: 2
guid: 3230f1117d4c11549b64332c8db164af
timeCreated: 1545819676
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- m_FallbackSurfaceImpact: {instanceID: 0}
- m_FallbackSurfaceType: {fileID: 11400000, guid: e616b14f5d2d0cf42bb5b4360f2b2089,
type: 2}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,57 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.SurfaceSystem
{
using UnityEngine;
/// <summary>
/// A ImpactEffect pairs the SurfaceImpact with a SurfaceEffect.
/// </summary>
[System.Serializable]
public struct ImpactEffect
{
#pragma warning disable 0649
[Tooltip("The SurfaceImpact which triggers the SurfaceEffect.")]
[SerializeField] private SurfaceImpact m_SurfaceImpact;
[Tooltip("The SurfaceEffect to spawn when triggered by the SurfaceImpact.")]
[SerializeField] private SurfaceEffect m_SurfaceEffect;
#pragma warning restore 0649
public SurfaceImpact SurfaceImpact { get { return m_SurfaceImpact; } }
public SurfaceEffect SurfaceEffect { get { return m_SurfaceEffect; } }
}
/// <summary>
/// Maps a texture to a set of UV coordinates.
/// </summary>
[System.Serializable]
public struct UVTexture
{
[Tooltip("The texture to map the UV coordinates to.")]
[SerializeField] private Texture m_Texture;
[Tooltip("The UV coordinates of the texture.")]
[SerializeField] private Rect m_UV;
public Texture Texture { get { return m_Texture; } set { m_Texture = value; } }
public Rect UV { get { return m_UV; } set { m_UV = value; } }
}
/// <summary>
/// Represets a default surface listed within the SurfaceManager.
/// </summary>
[System.Serializable]
public struct ObjectSurface
{
[Tooltip("The type of surface represented.")]
[SerializeField] private SurfaceType m_SurfaceType;
[Tooltip("The textures which go along with the specified SurfaceType.")]
[SerializeField] private UVTexture[] m_UVTextures;
public SurfaceType SurfaceType { get { return m_SurfaceType; } set { m_SurfaceType = value; } }
public UVTexture[] UVTextures { get { return m_UVTextures; } set { m_UVTextures = value; } }
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 84f5cfae165e1744f99ffdb69769baac
timeCreated: 1508192337
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,24 +0,0 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.SurfaceSystem
{
using UnityEngine;
/// <summary>
/// The SurfaceType is the main surface concept used for spawning objects based on impact.
/// </summary>
public class SurfaceType : ScriptableObject
{
[Tooltip("The SurfaceImpactEffects array maps the SurfaceImpact object with the SurfaceEffect object.")]
[SerializeField] protected ImpactEffect[] m_ImpactEffects;
[Tooltip("Does the SurfaceType allow footprints?")]
[SerializeField] protected bool m_AllowFootprints = true;
public ImpactEffect[] ImpactEffects { get { return m_ImpactEffects; } }
public bool AllowFootprints { get { return m_AllowFootprints; } }
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 696b92c305704c84fb3f7a11d0c474fd
timeCreated: 1508165060
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: b34170890b9b9d1469d9b451fddc01dd, type: 3}
userData:
assetBundleName:
assetBundleVariant: