Контроллер персонажа от третьего лица масштабирует вертикальную местность в игровом движке UnityC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Контроллер персонажа от третьего лица масштабирует вертикальную местность в игровом движке Unity

Сообщение Anonymous »

Я работаю над игрой, используя Unity с контроллером персонажей от третьего лица StarterAssets, но столкнулся с проблемой, из-за которой мой персонаж может ходить, стоять и даже прыгать по вертикальным стенам. Такое поведение непреднамеренно, поскольку игроки не должны иметь возможность подниматься по вертикальным поверхностям, если они не поднимаются по лестнице.
Я хочу, чтобы персонаж не взбирался по вертикальным поверхностям, но при этом позволял ему двигаться дальше. склоны, по которым можно ходить. Единственным исключением для вертикального движения должен быть подъем по лестнице.
Код: https://assetstore.unity.com/packages/e ... er-assets- Thirdperson-updates. -in-new-charactercontroller-pa-196526

Код: Выделить всё

using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif

/* Note: animations are called via the controller for both the character and capsule using animator null checks*/

namespace StarterAssets
{

[RequireComponent(typeof(CharacterController))]

#if ENABLE_INPUT_SYSTEM
[RequireComponent(typeof(PlayerInput))]
#endif

public class ThirdPersonController : MonoBehaviour
{

[Header("Player")]
[Tooltip("Move speed of the character in m/s")]
public float MoveSpeed = 2.0f;

[Tooltip("Sprint speed of the character in m/s")]
public float SprintSpeed = 5.335f;

[Tooltip("How fast the character turns to face movement direction")]
[Range(0.0f, 0.3f)]
public float RotationSmoothTime = 0.12f;

[Tooltip("Acceleration and deceleration")]
public float SpeedChangeRate = 10.0f;

public AudioClip LandingAudioClip;
public AudioClip[] FootstepAudioClips;
[Range(0, 1)] public float FootstepAudioVolume = 0.5f;

[Space(10)]
[Tooltip("The height the player can jump")]
public float JumpHeight = 1.2f;

[Tooltip("The character uses its own gravity value. The engine default is -9.81f")]
public float Gravity = -15.0f;

[Space(10)]
[Tooltip("Time required to pass before being able to jump again. Set to 0f to instantly jump again")]
public float JumpTimeout = 0.50f;

[Tooltip("Time required to pass before entering the fall state. Useful for walking down stairs")]
public float FallTimeout = 0.15f;

[Header("Player Grounded")]
[Tooltip("If the character is grounded or not. Not part of the CharacterController built in grounded check")]
public bool Grounded = true;

[Tooltip("Useful for rough ground")]
public float GroundedOffset = -0.14f;

[Tooltip("The radius of the grounded check. Should match the radius of the CharacterController")]
public float GroundedRadius = 0.28f;

[Tooltip("What layers the character uses as ground")]
public LayerMask GroundLayers;

[Header("Cinemachine")]
[Tooltip("The follow target set in the Cinemachine Virtual Camera that the camera will follow")]
public GameObject CinemachineCameraTarget;

[Tooltip("How far in degrees can you move the camera up")]
public float TopClamp = 70.0f;

[Tooltip("How far in degrees can you move the camera down")]
public float BottomClamp = -30.0f;

[Tooltip("Additional degress to override the camera.  Useful for fine tuning camera position when locked")]
public float CameraAngleOverride = 0.0f;

[Tooltip("For locking the camera position on all axis")]
public bool LockCameraPosition = false;

// cinemachine
private float _cinemachineTargetYaw;
private float _cinemachineTargetPitch;

// player
private float _speed;
private float _animationBlend;
private float _targetRotation = 0.0f;
private float _rotationVelocity;
private float _verticalVelocity;
private float _terminalVelocity = 53.0f;

// timeout deltatime
private float _jumpTimeoutDelta;
private float _fallTimeoutDelta;

// animation IDs
private int _animIDSpeed;
private int _animIDGrounded;
private int _animIDJump;
private int _animIDFreeFall;
private int _animIDMotionSpeed;

#if ENABLE_INPUT_SYSTEM
private PlayerInput _playerInput;
#endif

private Animator _animator;
private CharacterController _controller;
private StarterAssetsInputs _input;
private GameObject _mainCamera;

private const float _threshold = 0.01f;

private bool _hasAnimator;

private bool IsCurrentDeviceMouse
{
get
{

#if ENABLE_INPUT_SYSTEM
return _playerInput.currentControlScheme == "KeyboardMouse";
#else
return false;
#endif

}
}

private void Awake()
{

// get a reference to our main camera
if (_mainCamera == null)
{

_mainCamera = GameObject.FindGameObjectWithTag("MainCamera");

}
}

private void Start()
{

_cinemachineTargetYaw = CinemachineCameraTarget.transform.rotation.eulerAngles.y;

_hasAnimator = TryGetComponent(out _animator);
_controller = GetComponent();
_input = GetComponent();
#if ENABLE_INPUT_SYSTEM
_playerInput = GetComponent
();
#else
Debug.LogError( "Starter Assets package is missing dependencies.  Please use Tools/Starter Assets/Reinstall Dependencies to fix it");
#endif

AssignAnimationIDs();

// reset our timeouts on start
_jumpTimeoutDelta = JumpTimeout;
_fallTimeoutDelta = FallTimeout;
}

private void Update()
{

_hasAnimator = TryGetComponent(out _animator);

JumpAndGravity();
GroundedCheck();
Move();

}

private void LateUpdate()
{

CameraRotation();

}

private void AssignAnimationIDs()
{

_animIDSpeed = Animator.StringToHash("Speed");
_animIDGrounded = Animator.StringToHash("Grounded");
_animIDJump = Animator.StringToHash("Jump");
_animIDFreeFall = Animator.StringToHash("FreeFall");
_animIDMotionSpeed = Animator.StringToHash("MotionSpeed");

}

private void GroundedCheck()
{

// set sphere position, with offset
Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z);
Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers, QueryTriggerInteraction.Ignore);

// update animator if using character
if (_hasAnimator)
{

_animator.SetBool(_animIDGrounded, Grounded);

}

}

private void CameraRotation()
{

// if there is an input and camera position is not fixed
if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition)
{

//Don't multiply mouse input by Time.deltaTime;
float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime;

_cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier;
_cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier;

}

// clamp our rotations so our values are limited 360 degrees
_cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);

// Cinemachine will follow this target
CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride, _cinemachineTargetYaw, 0.0f);

}

private void Move()
{

// set target speed based on move speed, sprint speed and if sprint is pressed
float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;

// a simplistic acceleration and deceleration designed to be easy to remove, replace, or iterate upon

// note: Vector2's == operator uses approximation so is not floating point error prone, and is cheaper than magnitude
// if there is no input, set the target speed to 0
if (_input.move == Vector2.zero) targetSpeed = 0.0f;

// a reference to the players current horizontal velocity
float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;

float speedOffset = 0.1f;
float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;

// accelerate or decelerate to target speed
if (currentHorizontalSpeed < targetSpeed - speedOffset || currentHorizontalSpeed > targetSpeed + speedOffset)
{

// creates curved result rather than a linear one giving a more organic speed change
// note T in Lerp is clamped, so we don't need to clamp our speed
_speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude, Time.deltaTime * SpeedChangeRate);

// round speed to 3 decimal places
_speed = Mathf.Round(_speed * 1000f) / 1000f;

}

else
{

_speed = targetSpeed;

}

_animationBlend = Mathf.Lerp(_animationBlend, targetSpeed, Time.deltaTime * SpeedChangeRate);
if (_animationBlend <  0.01f) _animationBlend = 0f;

// normalise input direction
Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;

// note: Vector2's != operator uses approximation so is not floating point error prone, and is cheaper than magnitude
// if there is a move input rotate player when the player is moving
if (_input.move != Vector2.zero)
{

_targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg + _mainCamera.transform.eulerAngles.y;
float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity, RotationSmoothTime);

// rotate to face input direction relative to camera position
transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);

}

Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;

// move the player
_controller.Move(targetDirection.normalized * (_speed * Time.deltaTime) + new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);

// update animator if using character
if (_hasAnimator)
{

_animator.SetFloat(_animIDSpeed, _animationBlend);
_animator.SetFloat(_animIDMotionSpeed, inputMagnitude);

}

}

private void JumpAndGravity()
{

if (Grounded)
{

// reset the fall timeout timer
_fallTimeoutDelta = FallTimeout;

// update animator if using character
if (_hasAnimator)
{

_animator.SetBool(_animIDJump, false);
_animator.SetBool(_animIDFreeFall, false);

}

// stop our velocity dropping infinitely when grounded
if (_verticalVelocity < 0.0f)
{

_verticalVelocity = -2f;

}

// Jump
if (_input.jump && _jumpTimeoutDelta = 0.0f)
{

_jumpTimeoutDelta -= Time.deltaTime;

}

}

else
{

// reset the jump timeout timer
_jumpTimeoutDelta = JumpTimeout;

// fall timeout
if (_fallTimeoutDelta >= 0.0f)
{

_fallTimeoutDelta -= Time.deltaTime;

}

else
{

// update animator if using character
if (_hasAnimator)
{

_animator.SetBool(_animIDFreeFall, true);

}

}

// if we are not grounded, do not jump
_input.jump = false;

}

// apply gravity over time if under terminal (multiply by delta time twice to linearly speed up over time)
if (_verticalVelocity < _terminalVelocity)
{

_verticalVelocity += Gravity * Time.deltaTime;

}

}

private static float ClampAngle(float lfAngle, float lfMin, float lfMax)
{

if (lfAngle < -360f) lfAngle += 360f;
if (lfAngle >  360f) lfAngle -= 360f;
return Mathf.Clamp(lfAngle, lfMin, lfMax);

}

private void OnDrawGizmosSelected()
{

Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f);
Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f);

if (Grounded) Gizmos.color = transparentGreen;
else Gizmos.color = transparentRed;

// when selected, draw a gizmo in the position of, and matching radius of, the grounded collider
Gizmos.DrawSphere(new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z), GroundedRadius);

}

private void OnFootstep(AnimationEvent animationEvent)
{

if (animationEvent.animatorClipInfo.weight > 0.5f)
{

if (FootstepAudioClips.Length > 0)
{

var index = Random.Range(0, FootstepAudioClips.Length);
AudioSource.PlayClipAtPoint(FootstepAudioClips[index], transform.TransformPoint(_controller.center), FootstepAudioVolume);

}

}

}

private void OnLand(AnimationEvent animationEvent)
{

if (animationEvent.animatorClipInfo.weight > 0.5f)
{

AudioSource.PlayClipAtPoint(LandingAudioClip, transform.TransformPoint(_controller.center), FootstepAudioVolume);

}

}

}

}
Я пробовал использовать SphereCast, чтобы определить, когда игрок пытается масштабироваться по вертикальной стене, но мне не удалось заставить его работать должным образом. Я новичок в Unity и, возможно, неправильно подхожу к этой проблеме. Итак, я решил начать все сначала и вернуться к настройке контроллера персонажа по умолчанию.


Подробнее здесь: https://stackoverflow.com/questions/790 ... ame-engine
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»