@zackarhino
Hi zackarhino,
I’m working on a similar scenario in 3 dimensions, and here’s what I can contribute…
I think you’re getting stuck between two different coordinate systems, and this is causing you two levels of problem.
First is the different coordinate axies - The world scene coordinate system has its origin at a virtual point arbitrarily called (0,0) or (0,0,0) in 3D, and the gameObject translations, rotations, etc. are based on this origin, with positive x extending to the right, and positive y extending up. The mouse position however, uses a display-screen based coordinate system with the origin (0,0) at the top left corner of the screen with positive x extending to the right, and positive y extending down.
Second is the different scale for these systems. The world scene uses arbitrary units to measure, and depending on your scene, and your scale, etc. a single unit (from x = 3 to x = 4) could mean any number of different things. The mouse position uses a scale measured in pixels, so a change in mouse position from x = 3 to x = 4 may have no bearing whatsoever on the motion of your cue.
One or the other, or both of these issues are likely why you’re getting apparently random rotations for your cue.
I took another tact, and rather than using mathematical calculations to determine the position, orbit, rotation etc. of the cue, I’ve created another object (called AimHere - just a unit sphere, and in my production build it will be invisible and have no physical effects on the world). I intend to make my version of the cue be a child object which attaches as a child to the my cue ball. As a child, any translation or rotation of the cue ball will automatically be transferred to the cue. Then I will use the transform.LookAt() method to orient my cue ball (and the cue will follow). Before attaching it as a child to the cue ball, it should be oriented to be pointing directly at the cue ball from the negative Z direction. I figure that the LookAt method would be easier, if I can solve the scale issue, because it will work without any math needed, regardless of where my cue ball is in the scene.
Here’s the sample script I have so far, however, I have not yet worked out the problem of scaling between pixels and world measurement. For testing purposes, my cue ball, and AimHere are unit spheres, and currently my cue is a cylinder primitive with a position of (0,0,0), a rotation of (90,0,0), and a scale of (0.1, 2.0, 0.1) - I’ll adjust it later. I had my cue ball located at (0,0,0), rotated (0,0,0) and scaled (1,1,1) when I attached the cue as its child. This is important, because the cue will maintain its relative position, rotation, and scale when its attached, so if you want to adjust it, detach it, make your adjustments, and then attach it again.
(If you run this with your scene window zoomed way out, you can see the AimHere object moving around way out there because of the translation between pixels and game units.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CueControl : MonoBehaviour
{
public GameObject AimHere;
private Event e;
private Screen theScreen;
private Vector2 theMousePosition;
private float screenWidth;
private float screenHeight;
private float xAdjust;
private float yAdjust;
// For interactions with the GUI system
private void OnGUI()
{
// Read the current event system actions
e = Event.current;
theMousePosition = e.mousePosition;
// There's still a scale issue in here that I haven't resolved yet, but hopefully this will get you started...
// Move the AimHere object to the adjusted position
AimHere.transform.position = new Vector3(theMousePosition.x + xAdjust, -1 * (theMousePosition.y + yAdjust), 0.0f);
}
// Use this for initialization
void Start ()
{
// Read screen dimensions for translation
screenWidth = Screen.width;
screenHeight = Screen.height;
xAdjust = screenWidth / -2;
yAdjust = screenHeight / -2;
}
// Update is called once per frame
void Update ()
{
// Aim my cue ball (and also the cue because it is a child) at the AimHere object
this.transform.LookAt(AimHere.transform.position);
}
}
I hope this was of some help!