UnityRef is currently in early development. Some features may be incomplete and/or not functioning.

UNITYREF

Your Pit Stop For Solving ANYTHING in Unity

physics

[Character] Restrict Object Radius Using Distance Clamping

Solution

transformvector mathmathematics

Unity 2021.x - Unity 6.3.x

Published 13 days ago

Issue

 A common requirement in 3D projects involves a target object following another object. The challenge arises in restricting the target object movement to a maxDistance from the player, preventing it from exceeding a defined radius. Traditional constraints often fail to provide the desired behavior for this positional limitation.

Calculate the intended position for your object. If Vector3.Distance from your parent position to this desired position exceeds maxDistance, normalize the direction vector and multiply it by maxDistance to clamp the object within the sphere.

Explanation

Instead of utilizing heavy constraint systems, a simpler programmatic approach is implemented to manage object distance. This involves calculating movement towards a target point and enforcing maxDistance relative to a designated parent object.

  1. Determine the intended new position of your object.
  2. Evaluate the distance between this new position and your parent current position.
  3. If the distance exceeds maxDistance, calculate the direction vector from your parent to the new position.
  4. Normalize that vector and scale it by maxDistance.
  5. Add the scaled vector back to your parent position to obtain the clamped result.

Additional Tips:

  • Use Vector3.SqrMagnitude when comparing distances to save processing cycles by avoiding square root operations.
  • Ensure this logic runs in LateUpdate so your object reacts to the final transformed position of your parent for that frame.

Copy


using UnityEngine;

public class PositionClamper : MonoBehaviour
{
    public Transform parentAnchor;
    public float maxDistance = 5.0f;
    public float moveSpeed = 10.0f;

    private void LateUpdate()
    {
        if (parentAnchor == null) return;

        Vector3 currentPos = transform.position;
        Vector3 targetPos = parentAnchor.position;

        // Calculate next frame position
        Vector3 potentialMove = Vector3.MoveTowards(currentPos, targetPos, moveSpeed * Time.deltaTime);

        // Check against constraint
        float distance = Vector3.Distance(parentAnchor.position, potentialMove);

        if (distance > maxDistance)
        {
            Vector3 directionFromParent = potentialMove - parentAnchor.position;
            Vector3 clampedDirection = directionFromParent.normalized * maxDistance;
            potentialMove = parentAnchor.position + clampedDirection;
        }

        transform.position = potentialMove;
    }
}

Related Posts Haven't quite found a solution to your problem? We think these posts might help you.

Content inspired by a Unity discussion post.