Skip to content

Commit

Permalink
Merge pull request #713 from uni-bremen-agst/694-avoid-player-leaving…
Browse files Browse the repository at this point in the history
…-the-scene-through-wallsfloor

694 avoid player leaving the scene through wallsfloor

Closes #694
  • Loading branch information
koschke authored Mar 2, 2024
2 parents 01cd535 + 2c7ab36 commit b54d37e
Show file tree
Hide file tree
Showing 3 changed files with 469 additions and 82 deletions.
43 changes: 39 additions & 4 deletions Assets/SEE/Controls/DesktopPlayerMovement.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using UnityEngine;
using SEE.GO;
using UnityEngine;

namespace SEE.Controls
{
Expand All @@ -22,11 +23,29 @@ private struct CameraState

private CameraState cameraState;

/// <summary>
/// Unity component that moves the player constrained by collisions.
/// It moves the player with its own <see cref="CharacterController.Move(Vector3)"/> method.
/// </summary>
private CharacterController controller;

[Tooltip("The code city which the player is focusing on.")]
public GO.Plane FocusedObject;

private void Start()
{
controller = gameObject.MustGetComponent<CharacterController>();

// The default layer should be ignored by the collider.
// LayerMasks are bit masks, so we need that 1 << shifting to get the right layer.
controller.excludeLayers = 1 << LayerMask.NameToLayer("Default");

// Defines the built-in collider of the CharacterController, by default the collider is a capsule.
// We chose the following values to minimize the collider to roughly fit around the player's head as a sphere.
controller.center = new Vector3(0.0f, 1.55f, 0.21f);
controller.radius = HeadRadius();
controller.height = 0.0f;

if (FocusedObject != null)
{
cameraState.Distance = 2.0f;
Expand All @@ -45,6 +64,21 @@ private void Start()
cameraState.FreeMode = true;
}
lastAxis = new Vector2(Input.mousePosition.x, Input.mousePosition.y);

// Returns the radius of the player's head.
float HeadRadius()
{
const string headName = "Root/Global/Position/Hips/LowerBack/Spine/Spine1/Neck/Head/HeadAdjust";
Transform head = transform.Find(headName);
if (head == null)
{
Debug.LogError($"Player {gameObject.name} does not have a child {headName}.\n");
return 1.0f;
}
// We want to fit the head completely into the CharacterController collider, so we use the maximum value
// to calculate the radius
return Mathf.Max(head.transform.localScale.x, head.transform.localScale.y, head.transform.localScale.z) / 2;
}
}

private void Update()
Expand Down Expand Up @@ -83,8 +117,7 @@ private void Update()
cameraState.Distance -= d;

HandleRotation();
transform.position = FocusedObject.CenterTop;
transform.rotation = Quaternion.Euler(cameraState.Pitch, cameraState.Yaw, 0.0f);
transform.SetPositionAndRotation(FocusedObject.CenterTop, Quaternion.Euler(cameraState.Pitch, cameraState.Yaw, 0.0f));
transform.position -= transform.forward * cameraState.Distance;
}
else // cameraState.freeMode == true
Expand Down Expand Up @@ -116,7 +149,9 @@ private void Update()
}
velocity.Normalize();
velocity *= speed;
transform.position += velocity;
// The following two lines may look strange, yet both are actually needed.
controller.Move(velocity); // this is the actual movement
controller.Move(Vector3.zero); // this prevents the player from sliding without input

HandleRotation();
// Players Yaw
Expand Down
Loading

0 comments on commit b54d37e

Please sign in to comment.