Mathematics not working properly in unity - unity3d

I am trying to make a volleyball scene in unity. What I want is to create a scene where two NPCs are throwing the ball at each other. And I want the ball to land on random spots and the NPCs to reach the spot at the same time as the ball reaches the point. Now I am using the parabola equations to calculate where the ball should land and how much time will it take to get there. The time and the landing spot are working fine. But I can't seem to get the NPCs there at the exact time. I am using the following coroutine to move the NPC and the ball. The ball reaches the point on time but somehow the NPC reaches late.
IEnumerator playOneRound()
{
//this is the point where the ball is going to land
currentMovePoint.transform.position = currentRandomObjects[Random.Range(0, currentRandomObjects.Length)].transform.position;
parabolaStartPoint.transform.position = currentStartPoint.transform.position;
parabolaEndPoint.transform.position = currentBallPoint.transform.position;
ballController.FollowParabola();
//this is the time in which the ball will reach the end point of the parabola
time = ballController.GetDuration();
//this is the distance between the NPC and the point where the ball will land
distance = Vector3.Distance(currentPlayer.transform.position, currentMovePoint.transform.position);
speed = distance / time;
// clockspeed here is the amount of seconds I am going to wait for each iteration.
// so basically I am converting the the speed from distance-unit/second to
// distance-unit/clockspeed
distancePerClock = speed * clockSpeed;
while (Vector3.Distance(currentPlayer.transform.position, currentMovePoint.transform.position) > 0.1f)
{
currentPlayer.transform.position = Vector3.MoveTowards(currentPlayer.transform.position, currentMovePoint.transform.position, distancePerClock);
yield return new WaitForSeconds(clockSpeed);
}
}
The math seems to be right on paper. But somehow it's not working here. Am I missing something?

Related

How to make a model appear in front of AR Camera after the session starts using ARFoundation?

I was looking to update the ARcamera position.I am doing ImageTracking project.It detects an image and a corresponding prefab is shown in front of the camera.It starts playing an animation.After the animation I want the prefab to come really close towards the camera.When I give the code prefab.position=ARcamera.position; after animation code,I think the prefab goes to the initial position where the ARCamera was when the app had started that is (0,0,0).
How to make the prefab come really close towards the front camera.
speed = 10f;
float step = speed * Time.deltaTime;
Showprefabs.transform.GetChild(0).position = Vector3.MoveTowards(Showprefabs.transform.GetChild(0).position,
new Vector3(Arcam.transform.position.x, Arcam.transform.position.y + 0.2f,
Arcam.transform.position.z + 6.3f), step);
//The values 0.2f and 6.3f I added using the Editor to make the prefab come near the camera(But in world position it is different.)
First of all I hope by "prefab" you mean already Instantiated GameObject. It makes no sense to move a prefab ;)
You tried to calculate the target position but did it with World-Space coordinates.
You probably want to do something like
var targetObject = Showprefabs.transform.GetChild(0);
var currentPosition = targetObject.position;
var targetPosition = Arcam.transform.position
// Place it 60cm in front of the camera
+ Arcam.transform.forward * 0.6f
// additionally move it "up" 20cm perpendicular to the view direction
+ Arcam.transform.up * 0.2f;
targetObject.position = Vector3.MoveTowards(currentPosition, targetPosition, step * Time.deltaTime);
If you want that movement a bit smoother so it moves slower if already close and faster if further away you might be interested in rather using Vector3.Lerp here
public float smoothFactor = 0.5f;
targetObject.position = Vector3.Lerp(currentPosition, targetPosition, smoothFactor);
Where a smoothFactor of 0.5 reads: Every frame set the object to a position in the center of the currentPosition and targetPosition. A value closer to 0 results in slower movement, closer to 1 in faster reaching the targetPosition.
Note that actually this approach will never really fully arrive at the targetPosition but only come very very close but usually this doesn't matter in AR where the Camera constantly moves a bit anyway.

How to normalize Sprite movement in Java2D graphics to account for Screen Resolution

I am trying to build a 2D video game using JavaFX. There is a submarine at the bottom of the screen that fires torpedos. I have noticed that if I fire a torpedo on an Angle it travels at a faster rate, than if say I fired it straightup where is goes directly North. I'm assuming the difference in rates is because the screen is a rectangle, and when moving on a diagonal you are covering more distance.
Are there techniques to account for this, so you can get a constant rate of movement, regardless of the angle of travel of the projectile? I am writing the game using JavaFX under Eclipse.
Appreciate any help with this!
Thanks!
Since you are already firing in different directions, I'm assuming you have a velocity vector defined by two components (x, y). In JavaFX such a vector can be represented by Point2D. Given the speed you want the projectile to travel at, you can do the following:
public void fire() {
// the point at which you are shooting
Point2D target = ...
// the point from where you are shooting
Point2D source = ...
// the projectile speed per frame
double speed = ...
// velocity vector to be used to move
// the projectile at constant speed per frame
Point2D velocity = target.subtract(source).normalize().multiply(speed);
}
UPDATE: (included vector generation from angle)
In case you do not know the target point, you can obtain the vector from the angle you use to shoot:
public void fire() {
double angleDegrees = ...
double angleRadians = Math.toRadians(angleDegrees);
// the point from where you are shooting
Point2D source = ...
// the projectile speed per frame
double speed = ...
Point2D shootingVector = new Point2D(Math.cos(angleRadians), Math.sin(angleRadians));
// velocity vector to be used to move
// the projectile at constant speed per frame
Point2D velocity = shootingVector.normalize().multiply(speed);
}

How to track node movement after contact in SpriteKit

I have a ball node and a hole node. I want to detect when will the ball fall into the hold.
Currently I'm using didBeginContact, but it only gives me the distance of two nodes at the begin of contact, in which case the ball won't necessarily fall into the hole (it falls when distance between two centers < hole's radius).
Is there a way I can track the position of the ball after the contact had happened?
You can add invisible SKSpriteNodes and track when the ball touches them. You would have node1 just in top of the hole (a zone that the ball MUST go through - or touch - before entering the hole) before going into the hole, and node2 just after the hole (again, a zone that the ball MUST go through - or touch - after entering the hole).
If the ball touches node1 but not node2, you know it was almost going into the hole but then it didn't. If the ball touches node2, you know the ball is trying to go through the hole from the bottom part.
I guess you can make a physics body of a hole a lot smaller. That way, when contact occurs, you will be sure that ball can fall into a hole. Take a look at this picture (second example):
On top of that as an additional idea, when contact is detected, you can let ball to move little more, and then scale it down to make impression of falling.
There is no need to test for a contact between the ball and the hole, since it doesn't tell you if the objective was completed. Alternatively, you can simply add a check in didSimulatePhysics to see if the ball is sufficiently close to the hole before starting the falling animation sequence. For example,
override func didSimulatePhysics() {
let dx = ball.position.x - hole.position.x
let dy = ball.position.y - hole.position.y
let distance = sqrt(dx*dx+dy*dy)
if (distance < hole.size.width / 2.0) {
// Start falling animation sequence
}
}
Optionally, you can test if the ball is moving fast enough to skip over the hole by
override func didSimulatePhysics() {
let dx = ball.position.x - hole.position.x
let dy = ball.position.y - hole.position.y
let distance = sqrt(dx*dx+dy*dy)
if (distance < hole.size.width / 2.0) {
// Check if the ball is moving fast
let vx = ball.physicsBody!.velocity.dx
let vy = ball.physicsBody!.velocity.dy
let speed = sqrt(vx*vx+vy*vy)
if (speed < minSpeedToSkipOverHole) {
// Start falling animation sequence
}
}
}
This problem is solved by this: I maintain a possible_falling_list of all contacted holes for each ball and use another timer to frequently check if a ball is falling into any hole. Since the list is small for each ball, the performance is not an issue.

Move Object by dragging (mobile) makes the balls fall from the cup

I have this cup that contains balls inside. All 2D
I am using Rigidbody2d and Collider2d.
When running in unity and moving the cup (with arrow keys) the balls stay inside the cup. I also added drag movement for Android touch to move the cup.
The problem is that when moving the cup too fast (by draging) the balls fall from the cup collider (using Polygon colider 2d).
Code for movement is:
public float speed = 0.1F;
void Update() {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
transform.Translate(-touchDeltaPosition.x * speed, -touchDeltaPosition.y * speed, 0);
}
}
I tried to play with the speed parameter but it wont really help. if the cup movement is too slow it is not very useful for me.
I believe it is related the velocity/force of the ball or cup which makes the cup collider miss...
Any help on this would be appreciated greatly!
it is because you are moving it by changing the position of the cup, that means that when you move it fast, it disappears, and reappears where you dragged it, leaving the balls behind, and then they fall. I had the same thing where my objects would just go through the walls and out of the camera area. I fixed that by using AddForce. This makes the cup move, position by position over to where you dragged. this bumps the balls along, and they stay in the cup. This is what I guess is going on. If you use velocity that would work to.
you could rather than transform.Translate, you could find the vector to where you want to move to.
var direction = touchDeltaPosition - transform.position;
gameObject.rigidbody2D.velocity.x = direction.x * speed;
gameObject.rigidbody2D.velocity.y = direction.y * speed;
hope this solves it
The problem is that, when you're moving the cup too fast, at Frame 1 the ball is inside the cup, but at Frame 2 it's outside. You can reduce the value of "Fixed Timestep" (http://docs.unity3d.com/Manual/class-TimeManager.html) to increase the frequency of the physics calculations, or make the colliders larger.
If a ball in the cup will always stay in the cup, maybe you can turn off the physics of the ball once it's in the cup, or something along those lines.
Usually transform.Translate() is not very efficient when dealing with colliders, instead, you can try three other solutions:
1) rigidbody2D.AddForce(Vector2.Up * Input.GetAxis("Vertical"));
2) rigidbody2D.velocity = new Vector2(//write what you need);
3) which I consider the best solution for dealing with colliders and dragging is : MoveRigidbody2D
Well, this is what worked for me:
var newVec = new Vector2 (transform.position.x, transform.position.y);
var touchDeltaPosition = Input.GetTouch(0).deltaPosition*touchSpeed;
var direction = touchDeltaPosition- newVec;
rigidbody2D.AddForce(direction);

object stop falling when reach a specific point in unity3d

I am making a game in which the balls are falling down on a plane one ball fall over the other ball and they make a line, which goes from bottom to top. I want that at certain point on y axis the ball stop falling. Don't know how to do it the code I used until now for balls to fall down is:
function calling(){
functionsRandom.Range(0, functions.Length);
}
function sphereA() {
var go = Instantiate(sphere,new Vector3(Random.Range(-3, 3),Random.Range(-3,3),-12.78451),Quaternion.identity);
go.renderer.material.color = Color(Random.value, Random.value, Random.value);
}
function sphereB() {
var go = Instantiate(sphere1,new Vector3(Random.Range(-3, 3),Random.Range(-3,3),-12.78451),Quaternion.identity);
go.renderer.material.color = Color(Random.value, Random.value, Random.value);
}
I used random.range, so that the ball falls from points between it both in x and y, for x it is working, but it is not working for y.
Add all the instantiated spheres to an array go[] instead of go. which are in line. Now at certain point where you want to stop generating other spheres, take the count of the sphere in the array. If the count is equal to the max limit. Then DON'T instantiate the spheres. If any doubts, come to unity3d chatroom.