Skip to content

Commit 13b11ca

Browse files
committed
Added final part of 08 interaction with balls
1 parent 4e22b3a commit 13b11ca

File tree

6 files changed

+121
-95
lines changed

6 files changed

+121
-95
lines changed

Assets/_10 Minute Physics/08 User Interaction/Grabber.cs

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ public class Grabber
77
//Data needed
88
private Camera mainCamera;
99

10-
1110
//Ball grabbing data
1211
private float distanceToBall;
1312

@@ -25,68 +24,77 @@ public Grabber(Camera mainCamera)
2524

2625

2726

28-
public void MyUpdate()
27+
public void StartGrab(InteractiveBall ball)
2928
{
30-
//Move the ball to the position of the ray if it has been grabbed
3129
if (grabbedBall != null)
3230
{
33-
//A ray from the mouse into the scene
34-
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
31+
return;
32+
}
33+
34+
//A ray from the mouse into the scene
35+
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
36+
37+
//Find if the ray hit a sphere
38+
CustomPhysicsRaycast(ray, out CustomHit hit, ball);
39+
40+
if (hit != null)
41+
{
42+
//Debug.Log("Ray hit");
3543

36-
Vector3 ballPos = ray.origin + ray.direction * distanceToBall;
44+
grabbedBall = hit.ball;
3745

38-
lastBallPos = grabbedBall.pos;
46+
//Move the ball to the ray because the ray may not have hit at the center of the ball
47+
Vector3 ballPosOnRay = UsefulMethods.GetClosestPointOnRay(grabbedBall.pos, ray);
3948

40-
grabbedBall.MoveGrabbed(ballPos);
49+
grabbedBall.StartGrab(ballPosOnRay);
50+
51+
lastBallPos = ballPosOnRay;
52+
53+
distanceToBall = (ray.origin - grabbedBall.pos).magnitude;
54+
}
55+
else
56+
{
57+
//Debug.Log("Ray missed");
4158
}
4259
}
4360

4461

45-
public void MyLateUpdate(InteractiveBall ball)
62+
63+
64+
public void MoveGrab()
4665
{
47-
//If we press left mouse button and the ball is not grabbed, then try to grab it
48-
if (Input.GetMouseButtonDown(0) && grabbedBall == null)
66+
if (grabbedBall == null)
4967
{
50-
//Debug.Log("Ray fired");
51-
52-
//A ray from the mouse into the scene
53-
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
68+
return;
69+
}
5470

55-
//Find if the ray hit a sphere
56-
CustomPhysicsRaycast(ray, out CustomHit hit, ball);
71+
//A ray from the mouse into the scene
72+
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
5773

58-
if (hit != null)
59-
{
60-
//Debug.Log("Ray hit");
74+
Vector3 ballPos = ray.origin + ray.direction * distanceToBall;
6175

62-
grabbedBall = hit.ball;
76+
lastBallPos = grabbedBall.pos;
6377

64-
//Move the ball to the ray because the ray may not have hit at the center of the ball
65-
Vector3 ballPosOnRay = UsefulMethods.GetClosestPointOnRay(grabbedBall.pos, ray);
78+
grabbedBall.MoveGrabbed(ballPos);
79+
}
6680

67-
grabbedBall.StartGrab(ballPosOnRay);
6881

69-
distanceToBall = (ray.origin - grabbedBall.pos).magnitude;
70-
}
71-
else
72-
{
73-
//Debug.Log("Ray missed");
74-
}
7582

83+
public void EndGrab()
84+
{
85+
if (grabbedBall == null)
86+
{
87+
return;
7688
}
7789

78-
//If we release left mouse, then ungrab the ball
79-
if (Input.GetMouseButtonUp(0) && grabbedBall != null)
80-
{
81-
//Add a velocity to the ball
82-
float vel = (grabbedBall.pos - lastBallPos).magnitude / Time.deltaTime;
90+
//Add a velocity to the ball
91+
float vel = (grabbedBall.pos - lastBallPos).magnitude / Time.deltaTime;
8392

84-
Vector3 dir = (grabbedBall.pos - lastBallPos).normalized;
93+
Vector3 dir = (grabbedBall.pos - lastBallPos).normalized;
8594

86-
grabbedBall.EndGrab(grabbedBall.pos, dir * vel);
95+
grabbedBall.EndGrab(grabbedBall.pos, dir * vel);
8796

88-
grabbedBall = null;
89-
}
97+
grabbedBall = null;
9098
}
9199

92100

@@ -97,6 +105,6 @@ private void CustomPhysicsRaycast(Ray ray, out CustomHit hit, InteractiveBall ba
97105
//hit = null;
98106

99107
//Assumer we have just spheres, then we need to do ray-sphere collision detection
100-
ball.IsRayHitting(ray, out hit);
108+
ball.IsRayHittingThisBall(ray, out hit);
101109
}
102110
}

Assets/_10 Minute Physics/08 User Interaction/InteractiveBall.cs

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -45,62 +45,13 @@ public void EndGrab(Vector3 pos, Vector3 vel)
4545
}
4646

4747

48-
//Ray-sphere collision detection
49-
//https://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/
50-
public void IsRayHitting(Ray ray, out CustomHit hit)
48+
public void IsRayHittingThisBall(Ray ray, out CustomHit hit)
5149
{
5250
hit = null;
5351

54-
Vector3 p = ray.origin;
55-
Vector3 dir = ray.direction;
56-
57-
Vector3 c = pos;
58-
float r = radius;
59-
60-
//This is the vector from p to c
61-
Vector3 vpc = c - p;
62-
63-
//Assume the ray starts outside of the sphere
64-
65-
//The closest point on the ray from the sphere center
66-
Vector3 pc = UsefulMethods.GetClosestPointOnRay(c, ray);
67-
68-
//Debug.DrawRay(pc, Vector3.up * 5f, Color.white, 20f);
69-
70-
//There is no intersection if the distance between the center of the sphere and the closest point on the ray is larger than the radius of the sphere
71-
if ((pc - c).sqrMagnitude > r * r)
52+
if (UsefulMethods.IsRayHittingSphere(ray, pos, radius, out float hitDistance))
7253
{
73-
//Debug.Log("No intersection from within algorithm");
74-
75-
return;
76-
}
77-
else
78-
{
79-
//Distance from pc to i1 (itersection point 1) by using the triangle pc - c - i1
80-
float dist_i1_pc = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow((pc - c).magnitude, 2f));
81-
82-
//The distance to the first intersection point (there are two because the ray is also exiting the sphere) from the start of the ray
83-
//But we don't care about exiting the sphere becase that intersection point is further away
84-
float dist_i1 = 0f;
85-
86-
//Ray start is outside sphere
87-
if (vpc.sqrMagnitude > r * r)
88-
{
89-
dist_i1 = (pc - p).magnitude - dist_i1_pc;
90-
}
91-
//Ray start is inside sphere
92-
else
93-
{
94-
dist_i1 = (pc - p).magnitude + dist_i1_pc;
95-
}
96-
97-
//Vector3 intersection = p + dir * dist_i1;
98-
99-
//Debug.DrawRay(intersection, Vector3.up * 5f, Color.white, 20f);
100-
101-
//float distance = (ray.origin - intersection).magnitude;
102-
103-
hit = new CustomHit(dist_i1, this);
54+
hit = new CustomHit(hitDistance, this);
10455
}
10556
}
10657

Assets/_10 Minute Physics/08 User Interaction/UserInteractionController.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,23 @@ private void Update()
3838
//Update the visual position of the ball
3939
ball.UpdateVisualPosition();
4040

41-
grabber.MyUpdate();
41+
grabber.MoveGrab();
4242
}
4343

4444

4545

4646
//User interactions should be in LateUpdate
4747
private void LateUpdate()
4848
{
49-
grabber.MyLateUpdate(ball);
49+
if (Input.GetMouseButtonDown(0))
50+
{
51+
grabber.StartGrab(ball);
52+
}
53+
54+
if (Input.GetMouseButtonUp(0))
55+
{
56+
grabber.EndGrab();
57+
}
5058
}
5159

5260

Assets/_10 Minute Physics/UsefulMethods.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,63 @@ public static Vector3 GetClosestPointOnLineSegment(Vector3 p, Vector3 a, Vector3
6363

6464

6565

66+
//Ray-sphere collision detection
67+
//https://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/
68+
public static bool IsRayHittingSphere(Ray ray, Vector3 sphereCenter, float radius, out float hitDistance)
69+
{
70+
Vector3 p = ray.origin;
71+
Vector3 dir = ray.direction;
72+
73+
Vector3 c = sphereCenter;
74+
float r = radius;
75+
76+
//This is the vector from p to c
77+
Vector3 vpc = c - p;
78+
79+
//Assume the ray starts outside of the sphere
80+
81+
//The closest point on the ray from the sphere center
82+
Vector3 pc = UsefulMethods.GetClosestPointOnRay(c, ray);
83+
84+
//Debug.DrawRay(pc, Vector3.up * 5f, Color.white, 20f);
85+
86+
//There is no intersection if the distance between the center of the sphere and the closest point on the ray is larger than the radius of the sphere
87+
if ((pc - c).sqrMagnitude > r * r)
88+
{
89+
//Debug.Log("No intersection from within algorithm");
90+
hitDistance = 0f;
91+
92+
return false;
93+
}
94+
else
95+
{
96+
//Distance from pc to i1 (itersection point 1) by using the triangle pc - c - i1
97+
float dist_i1_pc = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow((pc - c).magnitude, 2f));
98+
99+
//The distance to the first intersection point (there are two because the ray is also exiting the sphere) from the start of the ray
100+
//But we don't care about exiting the sphere becase that intersection point is further away
101+
float dist_i1 = 0f;
102+
103+
//Ray start is outside sphere
104+
if (vpc.sqrMagnitude > r * r)
105+
{
106+
dist_i1 = (pc - p).magnitude - dist_i1_pc;
107+
}
108+
//Ray start is inside sphere
109+
else
110+
{
111+
dist_i1 = (pc - p).magnitude + dist_i1_pc;
112+
}
113+
114+
//Vector3 intersection = p + dir * dist_i1;
115+
116+
//Debug.DrawRay(intersection, Vector3.up * 5f, Color.white, 20f);
117+
118+
//float distance = (ray.origin - intersection).magnitude;
119+
120+
hitDistance = dist_i1;
121+
122+
return true;
123+
}
124+
}
66125
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ Simulate the chaotic behavior of a triple pendulum with different mass
4141

4242
Catch and throw a ball with your mouse
4343

44-
TODO
44+
<img src="/_media/08-user-interaction.png" width="400">

_media/08-user-interaction.png

23 KB
Loading

0 commit comments

Comments
 (0)