Growing up, some of the most fun I've had with 
video games has been with casual golf games. One   day I saw someone on the Unity discord saying 
they couldn't find any mini golf tutorials on   youtube. So I decided to have a go at it it kind 
of turned into a multi-day thing because I was   having so much fun. I think there's a lot to share 
about what I learned when making this prototype.   In this video, we'll go over the fundamentals 
of creating a system that allows players to   click the ball and drag it in a direction 
to add a force. Before you, go make sure   to hit those like and subscribe buttons. It's 
absolutely free and it helps the channel a ton. I have my project set up here with 
my ball and a little enclosed area.   The gameObjects that create the enclosed 
area all have colliders attached to them.   And on my ball, I've attached a sphere collider 
and a rigid body.

On the rigidbody I've checked   'use gravity' and I've unchecked 'is kinematic'. 
I've also set interpolate to interpolate so that   things are a little bit smoother if we decide to 
make a camera follow the ball at any point. And   I've also set my collision detection to continuous 
dynamic. The mass drag and angular drag will all   change how the physics work with your ball so 
feel free to experiment with them. The same   can be said for all of the physics materials that 
have been applied to each of the colliders. Under   our ball game object we've also attached a line 
game object which contains a line renderer. In   order to get our ball to move when we click let's 
create a new script. I'll go to add component,   new script, and name this LineForce. Then I'll 
click 'create and add'. Unity will attach that   script to our game object and within our project 
in the assets folder it'll place that script.   We'll just drag this to our scripts folder 
to maintain organization.

On our game object,   I'll double click this LineForce to open this in 
visual studio. Let's get started by visualizing   our line so for a variable let's get a private 
line renderer. We'll call it lineRenderer.   And we'll want to assign it in the inspector 
so we'll make a serialized field here. Then   I'll make a private void DrawLine function 
which will take in the parameter of a vector3   which will be the world point. So on our 
line renderer we'll do a SetPositions equal to positions which we'll make in a second 
and set the lineRenderer.enabled   equal to true so that it shows.

Above 
this we'll make a local vector3 array called positions we'll set it equal to the 
current transform position of our game object   and the world point that we take in so in this 
particular case the transform.position will be   the center of the object that we're drawing from 
in this case it'll be the center of our ball and   the world point will be our click location in 
order to get our click location we're going   to do some ray casting i'm going to copy and 
paste a method we've used in a previous video   i won't detail it too much here because we've 
already gone over it in that video there's a   link in the description below to the timestamp of 
when we talk about that in case you want to learn   a little bit more but as a really quick overview 
of what's going on here we're measuring where our   mouse click is on the near and far clip planes 
of the camera then we're casting a ray between   those two points to see if it hit any colliders 
if it did we return the point at which it hit   if it didn't we return null that's why here 
we're returning a vector3 that is nullable   now we'll call both of these in an update 
function so i'll make a private void update   and i'll make a vector3 that is nullable called 
world point here which will be equal to our method   then i'll call an if here if not worldpoint has 
value if not then we'll return so what this is   doing is saying if there's no value for world 
point don't even worry about continuing into the   rest of the code here and just return returns 
like this are helpful so that you avoid nested   if statements so if our word point has a value 
then we'll call draw a line at the world point   value back in unity on our ball script we need to 
assign our line renderer assign it to that slot   then i'll click play to play test now you 
can see every frame a line is drawn from   the center of my game object to where my 
current mouse input intersects a collider   and this works when you change your camera angle 
but we don't want this line to show up all the   time we only wanted to show up when we clicked on 
our ball and when our ball is stationary so back   in our script let's add a couple booleans i'll 
add a private bull is idle and a private bull   is aiming then i'll make a new private void on 
mouse down or if is idle is aiming equals true   what this means is that when we click on 
our object which in this case is our ball   we'll check if our object is idle and if it is 
we'll allow ourselves to aim i'll also make a   new method or process aim within this i'll 
make an if statement for if we're not aiming   or if we're not idle we'll return and i'll move 
our functionality from update into this method   then in update i'll put our process aim function 
so every frame will do a check for if our ball   is moving or if we haven't clicked on our ball to 
enable aiming we'll just exit out of this function   early now we need to set our idle state for that 
we'll need our rigid body so i'll make a new   private rigid body and call it rigidbody 
then on awake i'll set my rigid body equal to   get component rigidbody while we're here 
i'll also set is aiming equal to false   by default and to ensure that my line render isn't 
drawing things that we don't want it to we'll set   our enabled equal to false now in our update 
i'll make an if statement that will check our dot rigidbody.velocity.mag to see if it is less 
than our stop velocity we'll have to make a new   variable for our stop velocity as well so i'll 
declare a private float stop velocity and set it   equal to 0.05 f and i want to see this inspector 
in case we want to change it so i'll serialize   this field so this will check whether our ball is 
below a certain speed that we set if it is that's   when we'll consider the ball stopped or idle but 
we actually want to make sure that it's stopped   so i'm going to call a stop method here that 
we haven't created and then i will create it   so i'll make a private void stop and when we call 
stop we will set our red body velocity equal to   vector 3 0 so we're stopping the velocity and 
we'll do the same for our angular velocity   and then we'll set our is idle equal to true 
now when we play test we don't start with   a line render but when we click on our ball 
it starts to draw a line and it matches our   cursor position now what we need to do is add 
our force in our process a method under draw a   line i'll add an if statement here for if input 
get mouse button up 0 and this will check if our   left mouse click has been raised if it has i'm 
going to call a shoot function that will make   and it will take in the same world point dot value 
i'll create a private void shoot with a hector 3 world point i'll set my is aiming equal to false 
i'll disable my line render and i'll make a new   vector3 horizontal world point and set it equal 
to a new vector 3 which will be our world point x   and then we'll use our transform position y and 
then our world point z because of the way that   we have things set up our raycast can be in any 
vertical space but what that means is that if   we're clicking on something that is vertically 
above our ball there will be a vertical force   that gets applied so instead of our using our 
world point directly we'll just use our transform   this ensures that the velocity that's getting 
applied is always horizontal with our game object   from our horizontal world point we'll be able 
to get the direction so we'll get a vector three   call this direction we'll set it equal to the 
difference of our our horizontal world point and   our transform dot position and we'll do a 
dot normalize so it has a magnitude of one   and then we'll also calculate the strength which 
we'll set equal to the vector three dot distance   and we'll put in our transformed position and our 
horizontal world point and then we'll add that to   our rigidbody so we'll do a rigidbody.addforce 
and i'll put in our direction we'll multiply it   by our strength and then we will also multiply 
it by our shot power which will be a valuable   set so up at the very top i'll copy my stop 
velocity because i'm going to have another   variable here but instead of stop velocity i will 
make this my shot power then back in unity on my   ball i will assign a shot power of 150 and this 
is just a number you can experiment with to get   different strengths of the force that you're 
adding now when i click play i can drag and   shoot my ball in any direction that i want however 
you'll notice that while i'm shooting i can still   shoot in another direction let's fix that back 
in our script after we add a force we're going   to want to set our is idle equal to false because 
now we're moving then our if statement here will   be what sets it back to true now when we play 
test we can shoot the ball and while it's moving   i won't be able to aim again however there's a 
sneaky bug in here so if i shoot it really slow   i'll be able to shoot it while it's moving the 
issue here is that we're doing everything in an   update but we're also doing physics methods 
like add force so to make our updates run at   the same time as the physics time step instead 
of using update we'll just use fixed update   now when i play test you can see that i don't 
get that bug and that's basically all there is   to it we're going to be doing a mini series on 
this mini golf prototype so if that's something   you're interested in make sure to subscribe and 
hit that notification bell so be alerted when   the next video in the series goes live and 
as always you can check the description down   below for the line force script that we created 
in this video and i'll see you in the next one you