I have a script that lets player move a Rigidbody in my game with a mouse, and I want some objects to snap to other objects' axis (let's say guide) when they are near. So when an object is close to the guide, it will move only along the guide's axis (for example only along guide.transform.up). My current logic is thet when a raycast hits the guide, it affects the position of an object. So the new position is:

transform.position + Vector3.Scale(guide.transform.position - hit.point, guide.transform.up)

Then I linear interpolate the result to get a smoother movement. It works only when guide.transform.up is facing up or right in the world space, but also I don't think that Vector3.Scale is a way to go with it, but I haven't found a method that can do what I'm trying here. Maybe I need to do some math here?

Edit: This is the code used for movement/rotation. It works fine:

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
LayerMask layerMask = LayerMask.GetMask("Default");

if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, layerMask) || lastTrigger)
      Vector3 hitPoint = lastTrigger ? triggerHitPoint : hit.point;
      rb.MovePosition(Vector3.Lerp(transform.position, GetNewPosition(hitPoint), moveSpeed));

      if (!updateRotation && (hit.normal == lastHitNormal || lastTrigger))
           if (initRotation)
               targetRotation = GetRotation();
               initRotation = false;

           transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotTime);
           rotTime += Time.deltaTime * rotationSpeed;
           rotTime = 0;
           initRotation = true;
           updateRotation = false;

      lastHitNormal = hit.normal;

So 2 functions GetRotation() and GetNewPosition() are replaced in child class (a class that should snap to axis when moving) with this:

protected override Vector3 GetNewPosition(Vector3 hitPoint)
    if (triggered)
        Vector3 movement = Vector3.Scale(triggerTransform.position - hitPoint, triggerTransform.up);
        return initHookPosition + movement;
    return base.GetNewPosition(hitPoint);

protected override Quaternion GetRotation()
    if (triggered)
        Quaternion faceUp = Quaternion.FromToRotation(transform.up, triggerTransform.up);
        Quaternion faceFront = Quaternion.FromToRotation(transform.right, triggerTransform.right);
        transform.up = triggerTransform.up;
        return transform.rotation;
    return base.GetRotation();

The rotation is bugged right now, but if I use transform.up = triggerTransform.up it works as intended, so no big deal.
Here is how it works: video on Google Drive

  • \$\begingroup\$ "It works only when guide.transform.up is facing up or right in the world space" — sounds like you want to use an absolute value, so that you don't negate your direction of movement when the guide faces left or down. Can you show us more of your code around this one line it might help us spot other opportunities for improvement. A screenshot of the perspective you use and the shapes of the moving/guide objects (or their colliders) could also help. \$\endgroup\$
    – DMGregory
    Nov 28 '21 at 13:24
  • \$\begingroup\$ I added more code and also a video of how it works right now. \$\endgroup\$
    – europe1
    Nov 28 '21 at 17:35

You must log in to answer this question.

Browse other questions tagged .