Hey everyone! Welcome back to gameDevBox. It's Arian here, and I'm so excited to have
you with me today. I have a video about the trajectory but for
2D purposes so I told myself to change those scripts to work on a 3D world, and this is
the result. This approach is for beginners and ensures
a smooth understanding of the code so follow me to show you step-by-step how it is implemented. I've set up two cameras, one orthographic
and one perspective, to demonstrate that the trajectory works in both scenarios. Some solutions may only work in perspective
mode, so having both is an advantage. In the scene, I've included a directional
light, an environment with walls and ground, and several ball game objects. Each ball has a sphere collider with a physics
material and a default rigid body. Additionally, each ball has a script called
"Ball." Let's explore the contents of the Ball script: The Ball script is simple. It initializes the Rigidbody it called rb
and provides a property pos for easy access to the object's position. The "Push" method is public and can be called
from other scripts. It takes a Vector3 parameter named force and
applies an impulse force to the Rigidbody (rb) using AddForce. The force applied is based on the input force
parameter and is applied in ForceMode.Impulse. then in the hierarchy, we have the levelManager
object, which has a level manager script and trajectory script. let's first disable the trajectory and see
the code in levelmanager. In the "Properties" section, we capture the
camera, push force, and the layer for our balls. Next, we introduce the "default ball," which
is an instance of the Ball script. Additionally, we have variables such as "isDragging,"
"startPoint" as a Vector3 for calculating the clicked position, "endPoint," "direction,"
"force," and "distance," all of which are important for our calculations. At the start, we obtain the camera reference. In the update loop, we take the mouse position
as a ray, which returns a ray projected from the camera through a screen point. If a left click occurs, we perform another
conditional check to action a raycast. The ray cast uses the obtained ray as the
fir st parameter and an "out RaycastHit hit" for storing the result data. We set the maximum distance to infinity, specify
that we want to interact only with the ball layer, and assign "ballLayer.value" to layer
parameters. Additionally, we set the "QueryTriggerInteraction"
to "Collide." If our ray hits an object with the ball layer
that has a collider, we set the time scale to 0.1 for slow-motion effects. and we set "isDragging" to true and assigned
"default ball" to the ball that was hit. We call the "OnDragStart" function, which
simply stores the mouse position in the startPoint variable. Now that "isDragging" is true, we check in
the update loop. If true, we call the "OnDrag" function, which
continuously stores the mouse position for each frame into the endpoint, calculates the
distance and direction, mul tiplies them by "pushforce," and stores the result in the
"force" variable. in the update loop, we check if the left-click
is released. If so, we set the time scale back to 1 and
"isDragging" to false. Following this, we call the "OnDragEnd" function,
which essentially invokes the "Push" method from the Ball script, passing the calculated
force as its parameter. press the play button, now we can drag the
balls and apply force to push them. Now, let's set up the trajectory. First, open the LevelManager and uncomment
these lines. Here, it gets the Trajectory instance, and
in OnDragStart, it calls the trajectory.show() function. In OnDrag, there is a line where it calls
the trajectory.updateDots() with two arguments: the first being the ball's position, and the
second being the force. in OnDragEnd, the Trajectory.hide() function
is called. Drag the Trajectory script into this section. I completely forgot to mention that you need
to create a layer and assign that layer to balls or any game object you want to push,
and then set that layer in here. Now, let's explore the Trajectory script. The dotsNumber is serializedField, setting
the desired number of dots to display when pushing. We have a GameObject, dotsParent, to store
the instantiated GameObjects. The dotsPrefab is the prefab we want to instantiate. There are also variables for the spacing between
dots and the scale range between the minimum and maximum values. This allows our dots to be larger near the
ball and smaller near the ground. we have dotsList, position, and float timestamp
variables. In the Start function, we call hide() and
the prepareDots function. Regarding hide and show, the show function
sets "dotsParent" to be active, while the hide function does the opposite. The prepareDots function runs only once. It instantiates the dots and scales each one
accordingly. Initially, all dots' scales are set to the
maximum. We also calculate "scaleFactor" as the maximum
scale divided by "dotsNumber." Then, in a for loop, we instantiate the dots,
set their parents to dotsParent, and at the end, we set the dots' scales to the "scale"
variable. We also check if the scale is bigger than
the minimum scale, and if so, we decrease the value. we had "updateDots" in OnDrag, this function
stores the space dots in a timestamp. It then calculates the x and z positions of
the dots in each frame based on the applied force multiply the timestamp plus the current
dot position. For the y position, it is the same but uses
the gravity values to decrease the y position in each frame. We set the position of each dot and repeat
the process for the following dots. I've set the number of dots to 25. For dotsParent, I've created an empty GameObject. As for the "dotsPrefab," I've used a simple
sphere with no additional elements; it's just a sphere. The dot spacing is set to 0.1, the minimum
scale for dots is 0.01, and the maximum scale is 0.25. That's all for the setup. Now, let's press the play button, and you'll
see that the trajectory is drawn without any issues. It works great. let's check the perspective camera. You have the flexibility to customize the
dots as you wish. For example, let's give them a simple cube. Alternatively, you can change the balls to
any game object of your preference. I've included the project link in the description. Thanks for watching! Feel free to follow GameDevBox for more tutorials
and tips. Don't forget to hit the like button. See you next time!