0
\$\begingroup\$
private void FixedUpdate()
    {
        int layerMask = 1 << 8;

        RaycastHit hit;
        // Does the ray intersect any objects excluding the player layer
        if (Physics.Raycast(hand.transform.position, hand.transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layerMask))
        {
            Debug.DrawRay(hand.transform.position, hand.transform.TransformDirection(Vector3.forward) * hit.distance, Color.red);
        }
    }

I don't see the ray drawn anywhere when running the game in the scene view window.

I found the problem when shooting the raycast from the hand the hand rotation seems to be wrong or maybe it's in the script. When I'm running the game the yellow raycast is pointing directly up and when the hand pointing a target the yellow direction is back and up directions that's why it's never red :

The hand part I'm trying to shoot raycast from is child of a child of the player.

Raycast

I added an empty GameObject position and rotation set to 0,0,0 and now it's shooting the raycast to the opposite direction not sure why :

Oppositre direction

The full script :

using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using TMPro;

[RequireComponent(typeof(Animator))]

public class IKControl : MonoBehaviour
{
    public InteractableItem[] lookObj = null;
    public Text text;
    public float weightDamping = 1.5f;
    public float maxDistance = 10f;
    public bool RightHandToTarget = false;
    public GameObject hand;

    private Animator animator;
    private InteractableItem lastPrimaryTarget;
    private float lerpEndDistance = 0.1f;
    private float finalLookWeight = 0;
    private bool transitionToNextTarget = false;

    void Start()
    {
        animator = GetComponent<Animator>();
    }

    // Callback for calculating IK
    void OnAnimatorIK()
    {
        if (lookObj != null)
        {
            InteractableItem primaryTarget = null;
            float closestLookWeight = 0;

            // Here we find the target which is closest (by angle) to the players view line
            foreach (InteractableItem target in lookObj)
            {
                Vector3 lookAt = target.transform.position - transform.position;
                lookAt.y = 0f;

                // Filter out all objects that are too far away
                //if (lookAt.magnitude > maxDistance) continue;
                if (lookAt.magnitude > target.distance) continue;

                float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
                float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
                if (lookWeight > 0.1f && lookWeight > closestLookWeight)
                {
                    closestLookWeight = lookWeight;
                    primaryTarget = target;
                }
            }

            if (primaryTarget != null)
            {
                if ((lastPrimaryTarget != null) && (lastPrimaryTarget != primaryTarget) && (finalLookWeight > 0f))
                {
                    // Here we start a new transition because the player looks already to a target but
                    // we have found another target the player should look at
                    transitionToNextTarget = true;
                }
            }

            // The player is in a neutral look position but has found a new target
            if ((primaryTarget != null) && !transitionToNextTarget)
            {
                lastPrimaryTarget = primaryTarget;
                //finalLookWeight = Mathf.Lerp(finalLookWeight, closestLookWeight, Time.deltaTime * weightDamping);
                finalLookWeight = Mathf.Lerp(finalLookWeight, 1f, Time.deltaTime * weightDamping);
                float bodyWeight = finalLookWeight * .75f;
                animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
                animator.SetLookAtPosition(primaryTarget.transform.position);

                if (RightHandToTarget)
                {
                    Vector3 relativePos = primaryTarget.transform.position - transform.position;
                    Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.7f * closestLookWeight);
                    animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
                }
            }

            // Let the player smoothly look away from the last target to the neutral look position
            if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
            {
                finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, Time.deltaTime * weightDamping);
                float bodyWeight = finalLookWeight * .75f;
                animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
                animator.SetLookAtPosition(lastPrimaryTarget.transform.position);

                if (RightHandToTarget)
                {
                    Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
                    Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.7f * closestLookWeight);
                    animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
                }

                if (finalLookWeight < lerpEndDistance)
                {
                    transitionToNextTarget = false;
                    finalLookWeight = 0f;
                    lastPrimaryTarget = null;
                }
            }

            // Show found object by the player
            if (primaryTarget != null)
            {
                text.text = primaryTarget.description;
            }
            else
            {
                text.text = "";
            }
        }
    }

    private void FixedUpdate()
    {
        int layerMask = 1 << 8;

        RaycastHit hit;
        // Does the ray intersect any objects excluding the player layer
        if (Physics.Raycast(hand.transform.position, hand.transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layerMask))
        {
            Debug.DrawRay(hand.transform.position, hand.transform.TransformDirection(Vector3.forward) * hit.distance, Color.red);
        }
        else
        {
            Debug.DrawRay(hand.transform.position, hand.transform.TransformDirection(Vector3.forward) * 1000, Color.yellow);
        }
    }
}
\$\endgroup\$
1
0
\$\begingroup\$

There are a few things to fix:

  • hand.transform.TransformDirection(Vector3.forward) is pointlessly complicated. Use hand.transform.forward.
  • You haven't specified a duration for the line, so it will only last 1 frame. Here I use a duration of 5 seconds to ensure that you don't miss it. You'll want to remove that part once you figure out what's wrong, or you'll have red lines all over the place.
  • Sometimes lines aren't visible because the line is too short. I multiply the length by 10 to hopefully make the line visible.
  • Log a message to the console when the raycast hits, so we know whether the line is getting drawn at all.
  • As suggested by DMGregory, draw a different color line when the raycast is not hitting (I chose blue) so we know where the hand is pointed at all times.

Code:

private void FixedUpdate()
{
    int layerMask = 1 << 8;

    RaycastHit hit;
    // Does the ray intersect any objects excluding the player layer
    if (Physics.Raycast(hand.transform.position, hand.transform.forward, out hit, Mathf.Infinity, layerMask))
    {
        Debug.Log("Raycast hit");
        Debug.DrawRay(hand.transform.position, hand.transform.forward * hit.distance * 10, Color.red, 5f);
    } else {
        Debug.DrawRay(hand.transform.position, hand.transform.forward * 10, Color.blue);
    }
}

I don't understand what you are saying about the yellow line. You should probably share the code that you're using to draw the yellow line.

\$\endgroup\$
8
  • \$\begingroup\$ DMGregory seems to have a habit now of deleting his suggestion-comments after they are implemented, but he did recommend the change. @DMGregory, I personally find this disorienting and would prefer you just left the comments. \$\endgroup\$ – Kevin Aug 20 '20 at 1:47
  • \$\begingroup\$ Sorry about that. One of our standard reasons to flag a comment for deletion is "no longer needed" - so in cases where the suggestion has been acted on, the comment is no longer needed and can be cleared out to allow the answer to stand on its own / give more visibility to future comments that add something novel. \$\endgroup\$ – DMGregory Aug 20 '20 at 1:53
  • \$\begingroup\$ Comments are transient; once a suggestion is integrated into the post, there is really no need to keep them around :) \$\endgroup\$ – Vaillancourt Aug 20 '20 at 1:54
  • 1
    \$\begingroup\$ And congratulations for your first 1k rep :) \$\endgroup\$ – Vaillancourt Aug 20 '20 at 1:54
  • \$\begingroup\$ Okay, fair enough. Thanks! \$\endgroup\$ – Kevin Aug 20 '20 at 2:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.