- Home /
Look At Mouse Cursor Instead Of Object
Hello, I'm using the HeadLookControll script by Unity but I'm trying to change the code a bit. The first script has a variable public Vector3 target = Vector3.zero;
and this line Vector3 lookDirWorld = (target - segment.lastTransform.position).normalized;
I'm not sure but i think it makes the character look at the target. This is the second script that you attach to an empty object (the object that the character will look at) so that the first script can work.
using UnityEngine;
using System.Collections;
public class CursorHit : MonoBehaviour
{
public HeadLookController headLook;
private float offset = 1.5f;
void LateUpdate ()
{
if (Input.GetKey(KeyCode.UpArrow))
offset += Time.deltaTime;
if (Input.GetKey(KeyCode.DownArrow))
offset -= Time.deltaTime;
Ray cursorRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(cursorRay, out hit))
{
transform.position = hit.point + offset * Vector3.down;
}
headLook.target = transform.position;
}
}
What i want to achieve is remove the second script because i want the character to follow the mouse cursor not an object by changing a line in the first script without using 2 different script.
Answer by Tony_T · Feb 06, 2017 at 04:18 PM
I found a solution, now it follows the mouse cursor and it doesn't require 2 scripts (You don't need CursorHit.cs). Here is the tweaked version of the HeadLookController for anyone that wants it:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class BendingSegment {
public Transform firstTransform;
public Transform lastTransform;
public float thresholdAngleDifference = 0;
public float bendingMultiplier = 0.6f;
public float maxAngleDifference = 30;
public float maxBendingAngle = 80;
public float responsiveness = 5;
internal float angleH;
internal float angleV;
internal Vector3 dirUp;
internal Vector3 referenceLookDir;
internal Vector3 referenceUpDir;
internal int chainLength;
internal Quaternion[] origRotations;
}
[System.Serializable]
public class NonAffectedJoints {
public Transform joint;
public float effect = 0;
}
public class HeadLookController : MonoBehaviour {
private float offset = 1.5f;
private Vector3 MouseCursor;
public Transform rootNode;
public BendingSegment[] segments;
public NonAffectedJoints[] nonAffectedJoints;
public Vector3 headLookVector = Vector3.forward;
public Vector3 headUpVector = Vector3.up;
public Vector3 target = Vector3.zero;
public float effect = 1;
public bool overrideAnimation = false;
void Start () {
if (rootNode == null) {
rootNode = transform;
}
// Setup segments
foreach (BendingSegment segment in segments) {
Quaternion parentRot = segment.firstTransform.parent.rotation;
Quaternion parentRotInv = Quaternion.Inverse(parentRot);
segment.referenceLookDir =
parentRotInv * rootNode.rotation * headLookVector.normalized;
segment.referenceUpDir =
parentRotInv * rootNode.rotation * headUpVector.normalized;
segment.angleH = 0;
segment.angleV = 0;
segment.dirUp = segment.referenceUpDir;
segment.chainLength = 1;
Transform t = segment.lastTransform;
while (t != segment.firstTransform && t != t.root) {
segment.chainLength++;
t = t.parent;
}
segment.origRotations = new Quaternion[segment.chainLength];
t = segment.lastTransform;
for (int i=segment.chainLength-1; i>=0; i--) {
segment.origRotations[i] = t.localRotation;
t = t.parent;
}
}
}
void LateUpdate () {
if (Time.deltaTime == 0)
return;
// Remember initial directions of joints that should not be affected
Vector3[] jointDirections = new Vector3[nonAffectedJoints.Length];
for (int i=0; i<nonAffectedJoints.Length; i++) {
foreach (Transform child in nonAffectedJoints[i].joint) {
jointDirections[i] = child.position - nonAffectedJoints[i].joint.position;
break;
}
}
// Handle each segment
foreach (BendingSegment segment in segments) {
Transform t = segment.lastTransform;
if (overrideAnimation) {
for (int i=segment.chainLength-1; i>=0; i--) {
t.localRotation = segment.origRotations[i];
t = t.parent;
}
}
Quaternion parentRot = segment.firstTransform.parent.rotation;
Quaternion parentRotInv = Quaternion.Inverse(parentRot);
// Desired look direction in world space
Vector3 lookDirWorld = (target - segment.lastTransform.position).normalized;
// Desired look directions in neck parent space
Vector3 lookDirGoal = (parentRotInv * lookDirWorld);
// Get the horizontal and vertical rotation angle to look at the target
float hAngle = AngleAroundAxis(
segment.referenceLookDir, lookDirGoal, segment.referenceUpDir
);
Vector3 rightOfTarget = Vector3.Cross(segment.referenceUpDir, lookDirGoal);
Vector3 lookDirGoalinHPlane =
lookDirGoal - Vector3.Project(lookDirGoal, segment.referenceUpDir);
float vAngle = AngleAroundAxis(
lookDirGoalinHPlane, lookDirGoal, rightOfTarget
);
// Handle threshold angle difference, bending multiplier,
// and max angle difference here
float hAngleThr = Mathf.Max(
0, Mathf.Abs(hAngle) - segment.thresholdAngleDifference
) * Mathf.Sign(hAngle);
float vAngleThr = Mathf.Max(
0, Mathf.Abs(vAngle) - segment.thresholdAngleDifference
) * Mathf.Sign(vAngle);
hAngle = Mathf.Max(
Mathf.Abs(hAngleThr) * Mathf.Abs(segment.bendingMultiplier),
Mathf.Abs(hAngle) - segment.maxAngleDifference
) * Mathf.Sign(hAngle) * Mathf.Sign(segment.bendingMultiplier);
vAngle = Mathf.Max(
Mathf.Abs(vAngleThr) * Mathf.Abs(segment.bendingMultiplier),
Mathf.Abs(vAngle) - segment.maxAngleDifference
) * Mathf.Sign(vAngle) * Mathf.Sign(segment.bendingMultiplier);
// Handle max bending angle here
hAngle = Mathf.Clamp(hAngle, -segment.maxBendingAngle, segment.maxBendingAngle);
vAngle = Mathf.Clamp(vAngle, -segment.maxBendingAngle, segment.maxBendingAngle);
Vector3 referenceRightDir =
Vector3.Cross(segment.referenceUpDir, segment.referenceLookDir);
// Lerp angles
segment.angleH = Mathf.Lerp(
segment.angleH, hAngle, Time.deltaTime * segment.responsiveness
);
segment.angleV = Mathf.Lerp(
segment.angleV, vAngle, Time.deltaTime * segment.responsiveness
);
// Get direction
lookDirGoal = Quaternion.AngleAxis(segment.angleH, segment.referenceUpDir)
* Quaternion.AngleAxis(segment.angleV, referenceRightDir)
* segment.referenceLookDir;
// Make look and up perpendicular
Vector3 upDirGoal = segment.referenceUpDir;
Vector3.OrthoNormalize(ref lookDirGoal, ref upDirGoal);
// Interpolated look and up directions in neck parent space
Vector3 lookDir = lookDirGoal;
segment.dirUp = Vector3.Slerp(segment.dirUp, upDirGoal, Time.deltaTime*5);
Vector3.OrthoNormalize(ref lookDir, ref segment.dirUp);
// Look rotation in world space
Quaternion lookRot = (
(parentRot * Quaternion.LookRotation(lookDir, segment.dirUp))
* Quaternion.Inverse(
parentRot * Quaternion.LookRotation(
segment.referenceLookDir, segment.referenceUpDir
)
)
);
// Distribute rotation over all joints in segment
Quaternion dividedRotation =
Quaternion.Slerp(Quaternion.identity, lookRot, effect / segment.chainLength);
t = segment.lastTransform;
for (int i=0; i<segment.chainLength; i++) {
t.rotation = dividedRotation * t.rotation;
t = t.parent;
}
}
// Handle non affected joints
for (int i=0; i<nonAffectedJoints.Length; i++) {
Vector3 newJointDirection = Vector3.zero;
foreach (Transform child in nonAffectedJoints[i].joint) {
newJointDirection = child.position - nonAffectedJoints[i].joint.position;
break;
}
Vector3 combinedJointDirection = Vector3.Slerp(
jointDirections[i], newJointDirection, nonAffectedJoints[i].effect
);
nonAffectedJoints[i].joint.rotation = Quaternion.FromToRotation(
newJointDirection, combinedJointDirection
) * nonAffectedJoints[i].joint.rotation;
}
if (Input.GetKey(KeyCode.UpArrow))
offset += Time.deltaTime;
if (Input.GetKey(KeyCode.DownArrow))
offset -= Time.deltaTime;
Ray cursorRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(cursorRay, out hit))
{
MouseCursor = hit.point + offset * Vector3.down;
}
target = MouseCursor;
}
// The angle between dirA and dirB around axis
public static float AngleAroundAxis (Vector3 dirA, Vector3 dirB, Vector3 axis) {
// Project A and B onto the plane orthogonal target axis
dirA = dirA - Vector3.Project(dirA, axis);
dirB = dirB - Vector3.Project(dirB, axis);
// Find (positive) angle between A and B
float angle = Vector3.Angle(dirA, dirB);
// Return angle multiplied with 1 or -1
return angle * (Vector3.Dot(axis, Vector3.Cross(dirA, dirB)) < 0 ? -1 : 1);
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220612110415im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Instantiated Object - Look At. 1 Answer
2D tranform.lookAt Problem 1 Answer
crane lifting cylinder held by fixed joint moves out of position when i rotate crane. 0 Answers
How do I make one GameObject Point Towards another GameObject in 2D? 1 Answer
How to use LookAt() to make a gameobject look at another gameobject slowly? 0 Answers