update
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.FirstPersonController.Camera.ViewTypes
|
||||
{
|
||||
using Opsive.Shared.Events;
|
||||
using Opsive.UltimateCharacterController.Character.Abilities;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The Combat ViewType a first person prespective that allows the camera and character to rotate together.
|
||||
/// </summary>
|
||||
[UltimateCharacterController.Camera.ViewTypes.RecommendedMovementType(typeof(Character.MovementTypes.Combat))]
|
||||
[UltimateCharacterController.StateSystem.AddState("Zoom", "f08c1d8b08898574baa7bd27c1b05e62")]
|
||||
public class Combat : FirstPerson
|
||||
{
|
||||
private bool m_RotateWithCharacter;
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the view type to the specified character.
|
||||
/// </summary>
|
||||
/// <param name="character">The character to attach the camera to.</param>
|
||||
public override void AttachCharacter(GameObject character)
|
||||
{
|
||||
if (m_Character != null) {
|
||||
EventHandler.UnregisterEvent<Ability, bool>(m_Character, "OnCharacterAbilityActive", OnAbilityActive);
|
||||
}
|
||||
|
||||
base.AttachCharacter(character);
|
||||
|
||||
if (m_Character != null) {
|
||||
m_RotateWithCharacter = false;
|
||||
EventHandler.RegisterEvent<Ability, bool>(m_Character, "OnCharacterAbilityActive", OnAbilityActive);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the camera according to the horizontal and vertical movement values.
|
||||
/// </summary>
|
||||
/// <param name="horizontalMovement">-1 to 1 value specifying the amount of horizontal movement.</param>
|
||||
/// <param name="verticalMovement">-1 to 1 value specifying the amount of vertical movement.</param>
|
||||
/// <param name="immediatePosition">Should the camera be positioned immediately?</param>
|
||||
/// <returns>The updated rotation.</returns>
|
||||
public override Quaternion Rotate(float horizontalMovement, float verticalMovement, bool immediatePosition)
|
||||
{
|
||||
// The character may be controlling the rotation rather than the camera.
|
||||
if (m_RotateWithCharacter || m_CharacterLocomotion.UsingRootMotionRotation) {
|
||||
m_CharacterRotation = m_CharacterTransform.rotation;
|
||||
} else {
|
||||
if (m_Pitch > 90 || m_Pitch < -90) {
|
||||
horizontalMovement *= -1;
|
||||
}
|
||||
m_Yaw += horizontalMovement;
|
||||
}
|
||||
|
||||
return base.Rotate(horizontalMovement, verticalMovement, immediatePosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The character's ability has been started or stopped.
|
||||
/// </summary>
|
||||
/// <param name="ability">The ability which was started or stopped.</param>
|
||||
/// <param name="active">True if the ability was started, false if it was stopped.</param>
|
||||
private void OnAbilityActive(Ability ability, bool active)
|
||||
{
|
||||
if (!(ability is MoveTowards)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Rotate with the camera so the camera will follow the character's rotation when the character is getting into position for Move Towards.
|
||||
m_RotateWithCharacter = active;
|
||||
|
||||
// When rotate with character is enabled the CharacterRotation quaternion will update to the character's current rotation so the camera moves with the
|
||||
// character rather than the character moving with the camera. Set to yaw to 0 to prevent a snapping when the CharacterRotation quaternion is updated.
|
||||
if (m_RotateWithCharacter) {
|
||||
m_Yaw = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38c7a521f0ea6054eb5ee38eb56ef20d
|
||||
timeCreated: 1510149837
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5327267428b549a4487c8d28d17be2f2
|
||||
timeCreated: 1493483781
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.FirstPersonController.Camera.ViewTypes
|
||||
{
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using Opsive.UltimateCharacterController.FirstPersonController.Character;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The FreeLook ViewType is a first person view type that allows the camera to rotate independently of the character's direction.
|
||||
/// </summary>
|
||||
[UltimateCharacterController.Camera.ViewTypes.RecommendedMovementType(typeof(Character.MovementTypes.FreeLook))]
|
||||
[UltimateCharacterController.StateSystem.AddState("Zoom", "538aa537a9f445e40b8a2c2758627962")]
|
||||
public class FreeLook : FirstPerson
|
||||
{
|
||||
[Tooltip("The minimum yaw angle (in degrees).")]
|
||||
[SerializeField] protected float m_MinYawLimit = -90;
|
||||
[Tooltip("The maximum yaw angle (in degrees).")]
|
||||
[SerializeField] protected float m_MaxYawLimit = 90;
|
||||
[Tooltip("The speed in which the camera should rotate towards the yaw limit when out of bounds.")]
|
||||
[Range(0, 1)] [SerializeField] protected float m_YawLimitLerpSpeed = 0.7f;
|
||||
|
||||
public float MinYawLimit { get { return m_MinYawLimit; } set { m_MinYawLimit = value; } }
|
||||
public float MaxYawLimit { get { return m_MaxYawLimit; } set { m_MaxYawLimit = value; } }
|
||||
public float YawLimitLerpSpeed { get { return m_YawLimitLerpSpeed; } set { m_YawLimitLerpSpeed = value; } }
|
||||
|
||||
private Transform m_FirstPersonObjectsTransform;
|
||||
private Vector3 m_LookDirection;
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the camera to the specified character.
|
||||
/// </summary>
|
||||
/// <param name="character">The character to attach the camera to.</param>
|
||||
public override void AttachCharacter(GameObject character)
|
||||
{
|
||||
m_FirstPersonObjectsTransform = null;
|
||||
|
||||
base.AttachCharacter(character);
|
||||
|
||||
if (m_Character != null) {
|
||||
var firstPersonObjects = m_Character.GetComponentInChildren<FirstPersonObjects>(true);
|
||||
if (firstPersonObjects == null) {
|
||||
// The component may have already been changed to be a child of the camera.
|
||||
firstPersonObjects = m_GameObject.GetComponentInChildren<FirstPersonObjects>(true);
|
||||
}
|
||||
// FirstPersonObjects won't exist if the character carries no items.
|
||||
if (firstPersonObjects != null) {
|
||||
m_FirstPersonObjectsTransform = firstPersonObjects.transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the camera according to the horizontal and vertical movement values.
|
||||
/// </summary>
|
||||
/// <param name="horizontalMovement">-1 to 1 value specifying the amount of horizontal movement.</param>
|
||||
/// <param name="verticalMovement">-1 to 1 value specifying the amount of vertical movement.</param>
|
||||
/// <param name="immediatePosition">Should the camera be positioned immediately?</param>
|
||||
/// <returns>The updated rotation.</returns>
|
||||
public override Quaternion Rotate(float horizontalMovement, float verticalMovement, bool immediatePosition)
|
||||
{
|
||||
// Update the rotation. The yaw may have a limit.
|
||||
if (Mathf.Abs(m_MinYawLimit - m_MaxYawLimit) < 360) {
|
||||
// Determine the new rotation with the updated yaw.
|
||||
var targetRotation = MathUtility.TransformQuaternion(m_CharacterRotation, Quaternion.Euler(m_Pitch, m_Yaw, 0));
|
||||
var diff = MathUtility.InverseTransformQuaternion(Quaternion.LookRotation(Vector3.forward, m_CharacterLocomotion.Up), targetRotation * Quaternion.Inverse(m_CharacterTransform.rotation));
|
||||
// The rotation shouldn't extend beyond the min and max yaw limit.
|
||||
var targetYaw = MathUtility.ClampAngle(diff.eulerAngles.y, horizontalMovement, m_MinYawLimit, m_MaxYawLimit);
|
||||
m_Yaw += Mathf.Lerp(0, Mathf.DeltaAngle(diff.eulerAngles.y, targetYaw), m_YawLimitLerpSpeed);
|
||||
} else {
|
||||
m_Yaw += horizontalMovement;
|
||||
}
|
||||
|
||||
// Return the rotation.
|
||||
return base.Rotate(horizontalMovement, verticalMovement, immediatePosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the direction that the character is looking.
|
||||
/// </summary>
|
||||
/// <param name="lookPosition">The position that the character is looking from.</param>
|
||||
/// <param name="characterLookDirection">Is the character look direction being retrieved?</param>
|
||||
/// <param name="layerMask">The LayerMask value of the objects that the look direction can hit.</param>
|
||||
/// <param name="useRecoil">Should recoil be included in the look direction?</param>
|
||||
/// <returns>The direction that the character is looking.</returns>
|
||||
public override Vector3 LookDirection(Vector3 lookPosition, bool characterLookDirection, int layerMask, bool useRecoil)
|
||||
{
|
||||
var rotation = m_FirstPersonObjectsTransform != null ? m_FirstPersonObjectsTransform.rotation : m_CameraController.Anchor.rotation;
|
||||
|
||||
// Cast a ray from the camera point in the forward direction. The look direction is then the vector from the look position to the hit point.
|
||||
RaycastHit hit;
|
||||
Vector3 hitPoint;
|
||||
if (Physics.Raycast(m_Transform.position, rotation * Vector3.forward, out hit, m_LookDirectionDistance, layerMask, QueryTriggerInteraction.Ignore)) {
|
||||
hitPoint = hit.point;
|
||||
} else {
|
||||
Vector3 position;
|
||||
if (useRecoil) {
|
||||
position = GetAnchorTransformPoint(m_PositionSpring.Value + m_SecondaryPositionSpring.Value);
|
||||
} else {
|
||||
position = lookPosition;
|
||||
}
|
||||
m_LookDirection.Set(0, 0, m_LookDirectionDistance);
|
||||
hitPoint = MathUtility.TransformPoint(position, rotation, m_LookDirection);
|
||||
}
|
||||
|
||||
return (hitPoint - lookPosition).normalized;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7c1a07dd3dd3ed4785bdc77ae37d64d
|
||||
timeCreated: 1510149837
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,430 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.FirstPersonController.Camera
|
||||
{
|
||||
using Opsive.Shared.Events;
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.FirstPersonController.Character.Identifiers;
|
||||
using Opsive.UltimateCharacterController.FirstPersonController.Items;
|
||||
using Opsive.UltimateCharacterController.Camera;
|
||||
using Opsive.UltimateCharacterController.Character;
|
||||
using Opsive.UltimateCharacterController.Character.Identifiers;
|
||||
using Opsive.UltimateCharacterController.Items;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the first and third person materials so multiple cameras can render the scene within the same instance.
|
||||
/// </summary>
|
||||
public class MaterialSwapper : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies which renderers should be swapped.
|
||||
/// </summary>
|
||||
private enum SwapMask
|
||||
{
|
||||
FirstPerson = 1, // The first person perspective renderers should be swapped.
|
||||
ThirdPerson = 2, // The third person perspective renderers should be swapped.
|
||||
}
|
||||
|
||||
[Tooltip("The material used to make the object invisible but still cast shadows.")]
|
||||
[SerializeField] protected Material m_InvisibleMaterial;
|
||||
|
||||
private GameObject m_GameObject;
|
||||
private Camera m_Camera;
|
||||
private CameraController m_CameraController;
|
||||
private UltimateCharacterLocomotion m_CharacterLocomotion;
|
||||
private SwapMask m_SwapMask = 0;
|
||||
|
||||
private HashSet<Renderer> m_AddedFirstPersonRenderers;
|
||||
private List<Renderer> m_FirstPersonRenderers;
|
||||
private List<Material[]> m_FirstPersonOriginalMaterials;
|
||||
private List<Material[]> m_FirstPersonInvisibleMaterials;
|
||||
private HashSet<GameObject> m_FirstPersonBaseObjects;
|
||||
|
||||
private HashSet<Renderer> m_AddedThirdPersonRenderers;
|
||||
private List<Renderer> m_ThirdPersonRenderers;
|
||||
private List<Material[]> m_ThirdPersonOriginalMaterials;
|
||||
private List<Material[]> m_ThirdPersonInvisibleMaterials;
|
||||
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
private ThirdPersonController.Camera.ObjectFader m_ObjectFader;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
m_GameObject = gameObject;
|
||||
m_CameraController = m_GameObject.GetCachedComponent<CameraController>();
|
||||
if (m_CameraController == null) {
|
||||
// If the camera controller is null then the component has been added to the first person child camera.
|
||||
m_CameraController = gameObject.GetCachedParentComponent<CameraController>();
|
||||
m_SwapMask = SwapMask.FirstPerson;
|
||||
} else {
|
||||
var viewTypes = m_CameraController.ViewTypes;
|
||||
// The component exists on the main camera GameObject. If there is no child first person camera then the single component is responsible for
|
||||
// swapping both first and third person renderer materials.
|
||||
for (int i = 0; i < viewTypes.Length; ++i) {
|
||||
if (viewTypes[i] is ViewTypes.FirstPerson) {
|
||||
var firstPersonViewType = viewTypes[i] as ViewTypes.FirstPerson;
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_LWRP || ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP
|
||||
m_SwapMask = firstPersonViewType.OverlayRenderType == ViewTypes.FirstPerson.ObjectOverlayRenderType.SecondCamera ? SwapMask.ThirdPerson : (SwapMask.FirstPerson | SwapMask.ThirdPerson);
|
||||
#else
|
||||
m_SwapMask = firstPersonViewType.UseFirstPersonCamera ? SwapMask.ThirdPerson : (SwapMask.FirstPerson | SwapMask.ThirdPerson);
|
||||
#endif
|
||||
#if UNITY_EDITOR
|
||||
if ((m_SwapMask & SwapMask.ThirdPerson) != 0) {
|
||||
// Ensure the child camera has the Material Swapper component.
|
||||
if (firstPersonViewType.FirstPersonCamera != null) {
|
||||
var firstPersonMaterialSwapper = firstPersonViewType.FirstPersonCamera.GetComponent<MaterialSwapper>();
|
||||
if (firstPersonMaterialSwapper == null) {
|
||||
Debug.LogWarning("Warning: The First Person Camera should have the Material Swapper component added to the GameObject.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
m_ObjectFader = m_CameraController.GetComponent<ThirdPersonController.Camera.ObjectFader>();
|
||||
#endif
|
||||
}
|
||||
m_Camera = m_CameraController.GetComponent<Camera>();
|
||||
|
||||
// Instantiate the storage objects based on the swap mode.
|
||||
if ((m_SwapMask & SwapMask.FirstPerson) != 0) {
|
||||
m_AddedFirstPersonRenderers = new HashSet<Renderer>();
|
||||
m_FirstPersonRenderers = new List<Renderer>();
|
||||
m_FirstPersonOriginalMaterials = new List<Material[]>();
|
||||
m_FirstPersonInvisibleMaterials = new List<Material[]>();
|
||||
m_FirstPersonBaseObjects = new HashSet<GameObject>();
|
||||
}
|
||||
if ((m_SwapMask & SwapMask.ThirdPerson) != 0) {
|
||||
m_AddedThirdPersonRenderers = new HashSet<Renderer>();
|
||||
m_ThirdPersonRenderers = new List<Renderer>();
|
||||
m_ThirdPersonOriginalMaterials = new List<Material[]>();
|
||||
m_ThirdPersonInvisibleMaterials = new List<Material[]>();
|
||||
}
|
||||
|
||||
enabled = false;
|
||||
EventHandler.RegisterEvent<GameObject>(m_CameraController.gameObject, "OnCameraAttachCharacter", OnAttachCharacter);
|
||||
}
|
||||
|
||||
#if UNIVERSAL_RENDER_PIPELINE
|
||||
/// <summary>
|
||||
/// The component has been enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
UnityEngine.Rendering.RenderPipelineManager.beginCameraRendering += BeginCameraRendering;
|
||||
UnityEngine.Rendering.RenderPipelineManager.endCameraRendering += EndCameraRendering;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the component to the specified character.
|
||||
/// </summary>
|
||||
/// <param name="character">The handler to attach the camera to.</param>
|
||||
protected virtual void OnAttachCharacter(GameObject character)
|
||||
{
|
||||
// Don't do anything if the character is the same.
|
||||
if (m_CharacterLocomotion != null && character == m_CharacterLocomotion.gameObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_CharacterLocomotion != null) {
|
||||
// The character is being changed.
|
||||
if (m_FirstPersonRenderers != null) {
|
||||
m_AddedFirstPersonRenderers.Clear();
|
||||
m_FirstPersonRenderers.Clear();
|
||||
m_FirstPersonOriginalMaterials.Clear();
|
||||
m_FirstPersonInvisibleMaterials.Clear();
|
||||
m_FirstPersonBaseObjects.Clear();
|
||||
}
|
||||
if (m_ThirdPersonRenderers != null) {
|
||||
m_AddedThirdPersonRenderers.Clear();
|
||||
m_ThirdPersonRenderers.Clear();
|
||||
m_ThirdPersonOriginalMaterials.Clear();
|
||||
m_ThirdPersonInvisibleMaterials.Clear();
|
||||
}
|
||||
EventHandler.UnregisterEvent<bool>(m_CharacterLocomotion.gameObject, "OnCameraChangePerspectives", OnChangePerspectives);
|
||||
EventHandler.UnregisterEvent<Item>(m_CharacterLocomotion.gameObject, "OnInventoryAddItem", OnAddItem);
|
||||
EventHandler.UnregisterEvent(m_CharacterLocomotion.gameObject, "OnRespawn", OnRespawn);
|
||||
EventHandler.ExecuteEvent(m_CharacterLocomotion.gameObject, "OnCharacterIndependentFade", false, false);
|
||||
m_CharacterLocomotion = null;
|
||||
}
|
||||
|
||||
enabled = character != null;
|
||||
if (character == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_CharacterLocomotion = character.GetCachedComponent<UltimateCharacterLocomotion>();
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
// Force the character into using third person materials so the correct materials can be cached.
|
||||
var perspectiveMonitor = character.GetCachedComponent<ThirdPersonController.Character.PerspectiveMonitor>();
|
||||
perspectiveMonitor.UpdateThirdPersonMaterials(true);
|
||||
#endif
|
||||
|
||||
if ((m_SwapMask & SwapMask.FirstPerson) != 0) {
|
||||
var firstPersonBaseObjects = character.GetComponentsInChildren<FirstPersonBaseObject>(true);
|
||||
for (int i = 0; i < firstPersonBaseObjects.Length; ++i) {
|
||||
CacheFirstPersonRenderers(firstPersonBaseObjects[i].gameObject);
|
||||
// Remember the base objects so they are not added again if a runtime item is picked up.
|
||||
m_FirstPersonBaseObjects.Add(firstPersonBaseObjects[i].gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_SwapMask & SwapMask.ThirdPerson) != 0) {
|
||||
var thirdPersonObjects = character.GetComponentsInChildren<ThirdPersonObject>(true);
|
||||
for (int i = 0; i < thirdPersonObjects.Length; ++i) {
|
||||
CacheThirdPersonRenderers(thirdPersonObjects[i].gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
perspectiveMonitor.UpdateThirdPersonMaterials(false);
|
||||
#endif
|
||||
|
||||
EventHandler.RegisterEvent<bool>(m_CharacterLocomotion.gameObject, "OnCameraChangePerspectives", OnChangePerspectives);
|
||||
EventHandler.RegisterEvent<Item>(m_CharacterLocomotion.gameObject, "OnInventoryAddItem", OnAddItem);
|
||||
EventHandler.RegisterEvent(m_CharacterLocomotion.gameObject, "OnRespawn", OnRespawn);
|
||||
EventHandler.ExecuteEvent(m_CharacterLocomotion.gameObject, "OnCharacterIndependentFade", true, false);
|
||||
|
||||
// Assume the first person objects are not rendering.
|
||||
EnableThirdPersonMaterials();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The camera perspective between first and third person has changed.
|
||||
/// </summary>
|
||||
/// <param name="firstPersonPerspective">Is the camera in a first person perspective?</param>
|
||||
private void OnChangePerspectives(bool firstPersonPerspective)
|
||||
{
|
||||
enabled = firstPersonPerspective
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
|| m_ObjectFader != null
|
||||
#endif
|
||||
;
|
||||
if (!enabled) {
|
||||
EnableThirdPersonMaterials();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The inventory has added the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item that was added.</param>
|
||||
private void OnAddItem(Item item)
|
||||
{
|
||||
var perspectiveItems = item.GetComponents<PerspectiveItem>();
|
||||
for (int i = 0; i < perspectiveItems.Length; ++i) {
|
||||
if (perspectiveItems[i].FirstPersonItem) {
|
||||
if ((m_SwapMask & SwapMask.FirstPerson) != 0) {
|
||||
GameObject firstPersonObject;
|
||||
if (m_FirstPersonBaseObjects.Contains(perspectiveItems[i].Object)) {
|
||||
firstPersonObject = (perspectiveItems[i] as FirstPersonPerspectiveItem).VisibleItem;
|
||||
} else {
|
||||
firstPersonObject = perspectiveItems[i].Object;
|
||||
m_FirstPersonBaseObjects.Add(firstPersonObject);
|
||||
}
|
||||
|
||||
CacheFirstPersonRenderers(firstPersonObject);
|
||||
}
|
||||
} else if ((m_SwapMask & SwapMask.ThirdPerson) != 0) {
|
||||
CacheThirdPersonRenderers(perspectiveItems[i].Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches the renderers on the specified first person object.
|
||||
/// </summary>
|
||||
/// <param name="firstPersonObject">The first person object to cache the renderers of.</param>
|
||||
private void CacheFirstPersonRenderers(GameObject firstPersonObject)
|
||||
{
|
||||
if (firstPersonObject == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var renderers = firstPersonObject.GetComponentsInChildren<Renderer>(true);
|
||||
var emptyMaterial = new Material[0];
|
||||
for (int i = 0; i < renderers.Length; ++i) {
|
||||
if (m_AddedFirstPersonRenderers.Contains(renderers[i])) {
|
||||
continue;
|
||||
}
|
||||
m_AddedFirstPersonRenderers.Add(renderers[i]);
|
||||
|
||||
m_FirstPersonRenderers.Add(renderers[i]);
|
||||
m_FirstPersonOriginalMaterials.Add(renderers[i].materials);
|
||||
m_FirstPersonInvisibleMaterials.Add(emptyMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches the renderers on the specified third person object.
|
||||
/// </summary>
|
||||
/// <param name="thirdPersonObject">The third person object to cache the renderers of.</param>
|
||||
private void CacheThirdPersonRenderers(GameObject thirdPersonObject)
|
||||
{
|
||||
if (thirdPersonObject == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var renderers = thirdPersonObject.GetComponentsInChildren<Renderer>(true);
|
||||
for (int i = 0; i < renderers.Length; ++i) {
|
||||
if (m_AddedThirdPersonRenderers.Contains(renderers[i])) {
|
||||
continue;
|
||||
}
|
||||
m_AddedThirdPersonRenderers.Add(renderers[i]);
|
||||
|
||||
m_ThirdPersonRenderers.Add(renderers[i]);
|
||||
m_ThirdPersonOriginalMaterials.Add(renderers[i].materials);
|
||||
var invisibleMaterials = new Material[renderers[i].materials.Length];
|
||||
for (int j = 0; j < invisibleMaterials.Length; ++j) {
|
||||
invisibleMaterials[j] = m_InvisibleMaterial;
|
||||
}
|
||||
m_ThirdPersonInvisibleMaterials.Add(invisibleMaterials);
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNIVERSAL_RENDER_PIPELINE
|
||||
/// <summary>
|
||||
/// The camera has started to render.
|
||||
/// </summary>
|
||||
private void OnPreRender()
|
||||
{
|
||||
BeginCameraRendering(m_Camera);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The camera has stopped rendering.
|
||||
/// </summary>
|
||||
private void OnPostRender()
|
||||
{
|
||||
EndCameraRendering(m_Camera);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The camera has started to render.
|
||||
/// </summary>
|
||||
/// <param name="context">The context of the SRP.</param>
|
||||
/// <param name="camera">The camera that is rendering.</param>
|
||||
#if UNIVERSAL_RENDER_PIPELINE
|
||||
private void BeginCameraRendering(ScriptableRenderContext context, Camera camera)
|
||||
#else
|
||||
private void BeginCameraRendering(Camera camera)
|
||||
#endif
|
||||
{
|
||||
if (camera != m_Camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
if (m_ObjectFader != null) {
|
||||
m_ObjectFader.MultiCameraRender(true);
|
||||
}
|
||||
#endif
|
||||
if (!m_CharacterLocomotion.FirstPersonPerspective) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap the first person objects to the original material so the current camera can see the arms mesh.
|
||||
if ((m_SwapMask & SwapMask.FirstPerson) != 0) {
|
||||
for (int i = 0; i < m_FirstPersonRenderers.Count; ++i) {
|
||||
m_FirstPersonRenderers[i].materials = m_FirstPersonOriginalMaterials[i];
|
||||
}
|
||||
}
|
||||
|
||||
// The third person objects should be swapped to the invisible materials because the arms material will be rendered.
|
||||
if ((m_SwapMask & SwapMask.ThirdPerson) != 0) {
|
||||
for (int i = 0; i < m_ThirdPersonRenderers.Count; ++i) {
|
||||
m_ThirdPersonRenderers[i].materials = m_ThirdPersonInvisibleMaterials[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The camera has stopped rendering.
|
||||
/// </summary>
|
||||
/// <param name="context">The context of the SRP.</param>
|
||||
/// <param name="camera">The camera that stopped rendering.</param>
|
||||
#if UNIVERSAL_RENDER_PIPELINE
|
||||
private void EndCameraRendering(ScriptableRenderContext context, Camera camera)
|
||||
#else
|
||||
private void EndCameraRendering(Camera camera)
|
||||
#endif
|
||||
{
|
||||
if (camera != m_Camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if THIRD_PERSON_CONTROLLER
|
||||
if (m_ObjectFader != null) {
|
||||
m_ObjectFader.MultiCameraRender(false);
|
||||
}
|
||||
#endif
|
||||
if (!m_CharacterLocomotion.FirstPersonPerspective) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnableThirdPersonMaterials();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the materials for the third person mateirals.
|
||||
/// </summary>
|
||||
private void EnableThirdPersonMaterials()
|
||||
{
|
||||
// Swap the first person objects back to the invisible material so the separate arms are not seen by other cameras.
|
||||
if ((m_SwapMask & SwapMask.FirstPerson) != 0) {
|
||||
for (int i = 0; i < m_FirstPersonRenderers.Count; ++i) {
|
||||
m_FirstPersonRenderers[i].materials = m_FirstPersonInvisibleMaterials[i];
|
||||
}
|
||||
}
|
||||
|
||||
// The third person objects should be swapped back to the original materials so the full mesh is rendered by other cameras.
|
||||
if ((m_SwapMask & SwapMask.ThirdPerson) != 0) {
|
||||
for (int i = 0; i < m_ThirdPersonRenderers.Count; ++i) {
|
||||
m_ThirdPersonRenderers[i].materials = m_ThirdPersonOriginalMaterials[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The character has respawned.
|
||||
/// </summary>
|
||||
private void OnRespawn()
|
||||
{
|
||||
OnChangePerspectives(m_CharacterLocomotion.FirstPersonPerspective);
|
||||
}
|
||||
|
||||
#if UNIVERSAL_RENDER_PIPELINE
|
||||
/// <summary>
|
||||
/// The component has been disabled.
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
UnityEngine.Rendering.RenderPipelineManager.beginCameraRendering -= BeginCameraRendering;
|
||||
UnityEngine.Rendering.RenderPipelineManager.endCameraRendering -= EndCameraRendering;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The camera has been destroyed.
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
OnAttachCharacter(null);
|
||||
EventHandler.UnregisterEvent<GameObject>(m_CameraController.gameObject, "OnCameraAttachCharacter", OnAttachCharacter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 156a6ba7c7ad70d47a20a1845e89d7e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_InvisibleMaterial: {fileID: 2100000, guid: 0a580a5ea04fdab47941095489aa23b7,
|
||||
type: 2}
|
||||
executionOrder: 80
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,200 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.FirstPersonController.Camera.ViewTypes
|
||||
{
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.Camera;
|
||||
using Opsive.UltimateCharacterController.Camera.ViewTypes;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The TransformLook ViewType is a first person view type that will have the camera look in the forward direction relative to the target transform.
|
||||
/// </summary>
|
||||
public class TransformLook : ViewType
|
||||
{
|
||||
[Tooltip("The object that determines the position of the camera.")]
|
||||
[SerializeField] protected Transform m_MoveTarget;
|
||||
[Tooltip("The object that determines the rotation of the camera.")]
|
||||
[SerializeField] protected Transform m_RotationTarget;
|
||||
[Tooltip("The offset relative to the move target.")]
|
||||
[SerializeField] protected Vector3 m_Offset = new Vector3(0, 0.2f, 0.2f);
|
||||
[Tooltip("The radius of the camera's collision sphere to prevent it from clipping with other objects.")]
|
||||
[SerializeField] protected float m_CollisionRadius = 0.05f;
|
||||
[Tooltip("The speed at which the camera should move.")]
|
||||
[SerializeField] protected float m_MoveSpeed = 10;
|
||||
[Tooltip("The speed at which the view type should rotate towards the target rotation.")]
|
||||
[Range(0, 1)] [SerializeField] protected float m_RotationalLerpSpeed = 0.9f;
|
||||
[Tooltip("Should the pitch be restricted? If false the pitch can be changed by the player.")]
|
||||
[SerializeField] protected bool m_RestrictPitch = true;
|
||||
[Tooltip("The minimum pitch angle (in degrees), used if the pitch is not restricted.")]
|
||||
[HideInInspector] [SerializeField] protected float m_MinPitchLimit = -72;
|
||||
[Tooltip("The maximum pitch angle (in degrees), used if the pitch is not restricted.")]
|
||||
[HideInInspector] [SerializeField] protected float m_MaxPitchLimit = 72;
|
||||
[Tooltip("Should the yaw be restricted? If false the yaw can be changed by the player.")]
|
||||
[SerializeField] protected bool m_RestrictYaw = true;
|
||||
|
||||
public Transform MoveTarget { get { return m_MoveTarget; } set { m_MoveTarget = value; } }
|
||||
public Transform RotationTarget { get { return m_RotationTarget; } set { m_RotationTarget = value; } }
|
||||
public Vector3 Offset { get { return m_Offset; } set { m_Offset = value; } }
|
||||
public float CollisionRadius { get { return m_CollisionRadius; } set { m_CollisionRadius = value; } }
|
||||
public float MoveSpeed { get { return m_MoveSpeed; } set { m_MoveSpeed = value; } }
|
||||
public float RotationalLerpSpeed { get { return m_RotationalLerpSpeed; } set { m_RotationalLerpSpeed = value; } }
|
||||
public bool RestrictPitch { get { return m_RestrictPitch; } set { m_RestrictPitch = value; } }
|
||||
public float MinPitchLimit { get { return m_MinPitchLimit; } set { m_MinPitchLimit = value; } }
|
||||
public float MaxPitchLimit { get { return m_MaxPitchLimit; } set { m_MaxPitchLimit = value; } }
|
||||
public bool RestrictYaw { get { return m_RestrictYaw; } set { m_RestrictYaw = value; } }
|
||||
|
||||
public override Quaternion CharacterRotation { get { return m_CharacterTransform.rotation; } }
|
||||
public override bool FirstPersonPerspective { get { return true; } }
|
||||
public override float LookDirectionDistance { get { return m_Offset.magnitude; } }
|
||||
public override float Pitch { get { return m_Pitch; } }
|
||||
public override float Yaw { get { return m_Yaw; } }
|
||||
|
||||
private UnityEngine.Camera m_Camera;
|
||||
private RaycastHit m_RaycastHit;
|
||||
private float m_Pitch;
|
||||
private float m_Yaw;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the view type to the specified camera controller.
|
||||
/// </summary>
|
||||
/// <param name="cameraController">The camera controller to initialize the view type to.</param>
|
||||
public override void Initialize(CameraController cameraController)
|
||||
{
|
||||
base.Initialize(cameraController);
|
||||
|
||||
m_Camera = cameraController.gameObject.GetCachedComponent<UnityEngine.Camera>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the view type to the specified character.
|
||||
/// </summary>
|
||||
/// <param name="character">The character to attach the camera to.</param>
|
||||
public override void AttachCharacter(GameObject character)
|
||||
{
|
||||
base.AttachCharacter(character);
|
||||
|
||||
if (m_MoveTarget == null || m_RotationTarget == null) {
|
||||
if (m_Character == null) {
|
||||
return;
|
||||
}
|
||||
Transform moveTarget = m_CharacterTransform, rotationTarget = m_CharacterTransform;
|
||||
var characterAnimator = m_Character.GetCachedComponent<Animator>();
|
||||
if (characterAnimator != null) {
|
||||
moveTarget = characterAnimator.GetBoneTransform(HumanBodyBones.Head);
|
||||
rotationTarget = characterAnimator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
}
|
||||
|
||||
m_MoveTarget = moveTarget;
|
||||
m_RotationTarget = rotationTarget;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The view type has changed.
|
||||
/// </summary>
|
||||
/// <param name="activate">Should the current view type be activated?</param>
|
||||
/// <param name="pitch">The pitch of the camera (in degrees).</param>
|
||||
/// <param name="yaw">The yaw of the camera (in degrees).</param>
|
||||
/// <param name="characterRotation">The rotation of the character.</param>
|
||||
public override void ChangeViewType(bool activate, float pitch, float yaw, Quaternion characterRotation)
|
||||
{
|
||||
if (activate) {
|
||||
m_Pitch = m_RestrictPitch ? 0 : pitch;
|
||||
m_Yaw = m_RestrictYaw ? 0 : yaw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the ViewType's variables.
|
||||
/// </summary>
|
||||
/// <param name="characterRotation">The rotation of the character.</param>
|
||||
public override void Reset(Quaternion characterRotation)
|
||||
{
|
||||
m_Pitch = 0;
|
||||
m_Yaw = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the camera to face in the same direction as the target.
|
||||
/// </summary>
|
||||
/// <param name="horizontalMovement">-1 to 1 value specifying the amount of horizontal movement.</param>
|
||||
/// <param name="verticalMovement">-1 to 1 value specifying the amount of vertical movement.</param>
|
||||
/// <param name="immediateUpdate">Should the camera be updated immediately?</param>
|
||||
/// <returns>The updated rotation.</returns>
|
||||
public override Quaternion Rotate(float horizontalMovement, float verticalMovement, bool immediateUpdate)
|
||||
{
|
||||
var rotation = m_RotationTarget.rotation;
|
||||
if (!immediateUpdate) {
|
||||
rotation = Quaternion.Slerp(m_Transform.rotation, rotation, m_RotationalLerpSpeed);
|
||||
}
|
||||
|
||||
// Update the pitch and yaw if they are not restricted.
|
||||
if (!m_RestrictPitch) {
|
||||
if (Mathf.Abs(m_MinPitchLimit - m_MaxPitchLimit) < 180) {
|
||||
m_Pitch = MathUtility.ClampAngle(m_Pitch, -verticalMovement, m_MinPitchLimit, m_MaxPitchLimit);
|
||||
} else {
|
||||
m_Pitch -= verticalMovement;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_RestrictYaw) {
|
||||
if (m_Pitch > 90 || m_Pitch < -90) {
|
||||
horizontalMovement *= -1;
|
||||
}
|
||||
m_Yaw = MathUtility.ClampInnerAngle(m_Yaw + horizontalMovement);
|
||||
}
|
||||
|
||||
return rotation * Quaternion.Euler(m_Pitch, m_Yaw, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the camera to be in the target position.
|
||||
/// </summary>
|
||||
/// <param name="immediateUpdate">Should the camera be updated immediately?</param>
|
||||
/// <returns>The updated position.</returns>
|
||||
public override Vector3 Move(bool immediateUpdate)
|
||||
{
|
||||
// Ensure there aren't any objects obstructing the distance between the anchor offset and the target position.
|
||||
var collisionLayerEnabled = m_CharacterLocomotion.CollisionLayerEnabled;
|
||||
m_CharacterLocomotion.EnableColliderCollisionLayer(false);
|
||||
var targetPosition = m_MoveTarget.TransformPoint(m_Offset);
|
||||
var direction = targetPosition - m_MoveTarget.position;
|
||||
if (Physics.SphereCast(m_MoveTarget.position, m_CollisionRadius, direction.normalized, out m_RaycastHit, direction.magnitude + m_Camera.nearClipPlane,
|
||||
m_CharacterLayerManager.IgnoreInvisibleCharacterWaterLayers, QueryTriggerInteraction.Ignore)) {
|
||||
// Move the camera in if an object obstructed the view.
|
||||
targetPosition = m_RaycastHit.point + m_RaycastHit.normal * (m_Camera.nearClipPlane + m_CharacterLocomotion.ColliderSpacing);
|
||||
}
|
||||
m_CharacterLocomotion.EnableColliderCollisionLayer(collisionLayerEnabled);
|
||||
|
||||
return Vector3.MoveTowards(m_Transform.position, targetPosition, immediateUpdate ? float.MaxValue : Time.deltaTime * m_MoveSpeed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the direction that the character is looking.
|
||||
/// </summary>
|
||||
/// <param name="characterLookDirection">Is the character look direction being retrieved?</param>
|
||||
/// <returns>The direction that the character is looking.</returns>
|
||||
public override Vector3 LookDirection(bool characterLookDirection)
|
||||
{
|
||||
return m_CharacterTransform.forward;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the direction that the character is looking.
|
||||
/// </summary>
|
||||
/// <param name="lookPosition">The position that the character is looking from.</param>
|
||||
/// <param name="characterLookDirection">Is the character look direction being retrieved?</param>
|
||||
/// <param name="layerMask">The LayerMask value of the objects that the look direction can hit.</param>
|
||||
/// <param name="useRecoil">Should recoil be included in the look direction?</param>
|
||||
/// <returns>The direction that the character is looking.</returns>
|
||||
public override Vector3 LookDirection(Vector3 lookPosition, bool characterLookDirection, int layerMask, bool useRecoil)
|
||||
{
|
||||
return m_CharacterTransform.forward;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a509ec4c79f2ac646b717e5ae2e09675
|
||||
timeCreated: 1533168180
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user