unfortunately I have a supposedly simple "problem".
The Situation:
I want to code my first "space shooter ... or something like that" with SpriteKit
So I have (currently :-)):
One Node,
Three Buttons: 1 button for turning left, 1 for right & 1 for acceleration.
Turning is solved. Using impulse for giving the node a new direction
...The problem is :
Acceleration.
I also use the impulse for getting the node "forward". But it don't want to move forward in the direction in which the node was turned.
My ideas solving the Problem:
using the radiant of the zRotation, calculating the degrees, figuring out the CGVector via using "rad * cos(degree)" / "rad * sin(degree)".
result
the node is not moving in the direction it should. especially if the rad is a negative figure ... :-D
So question is: How can I set an impulse / velocity for moving my future spaceship forward to the set direction .
thanks for your help!
greetings
Sascha
The below code is taken from this video, where they are making a bullet go in the same direction as the space ship is pointing.
The adjusted rotation is required if your sprites texture orientation is pointing up, whereas SpriteKit uses the right direction as 0 rotation.
let speed: CGFloat = 1
let adjustedRotation = zRotation + (CGFloat.pi / 2)
let dx = speed * cos(adjustedRotation)
let dy = speed * sin(adjustedRotation)
spaceship?.physicsBody?.applyImpulse(CGVector(dx: dx, dy: dy))
Related
I am still new to coding in unity, so please be gentle XD ... I want to make a raycast that is hitting a collider to start a new raycast with the same direction but not starting from the point where it has hit, but just slightly forward along its direction (like a few centimeters or so, or whatever that might be in unity units ^^) ... the code snippet shows the second raycast after the first hit:
Physics.Raycast(firsthit.point, direction, out var hit, distance, HitLayerMask, QueryTriggerInteraction.Ignore)
So I figure I need to change the "firsthit.point" value(s) somehow using the "direction", but I just cant figure out how exactly. Any help would be highly appreciated.
Thanks, ANB_Seth
Try:
float distance = 1f;
Vector3 newPosition = firsthit.point + direction.normalized * distance;
Physics.Raycast(newPosition, direction, out var hit, distance, HitLayerMask, QueryTriggerInteraction.Ignore);
I started some programming in Unity just for fun a couple days ago.
So far my game (pretty much top-down shooter) consists of player flying in an asteroid field, in which lurk enemy ships. Player can shoot down asteroids and enemies, and enemy ships have missile turrets that "track" player.
Everything works fine until I decided that enemy ships shouldn't be able to rotate their turrets all the 360-way. Think of it as real-world battleship being unable to turn it's front turret (No.1) 180 degrees behind because turret No.2 is in the way.
Currently code for turret rotation is like this (this is not about making "gradual rotation", setting "rotation speed" or something, so please don't look at that!):
playerTarget = GameObject.FindGameObjectWithTag("Player");
chaseDirection = Quaternion.LookRotation(playerTarget.transform.position - transform.position);
newYaw = Mathf.Clamp(chaseDirection.eulerAngles.y, minYaw, maxYaw);
transform.rotation = Quaternion.Euler(0, newYaw, 0);
That works okay, until player flies behind enemy ship. As soon as player gets into turret's "possible rotation angle", it just snaps past "dead zone" to new direction if I don't turn it gradually with fixed angle, or is still stuck trying to rotate "past limit" until target (player) flies all around enemy ship so the angle to target is small enough for rotation direction to be calculated through "enabled" rotation zone, not through "dead zone".
An important thing is I am not looking for answer "how to make gradual rotation". I am looking about calculating rotation direction!
I thought about coding enemy to start rotating turret in counter-direction as soon as player passes "directly behind" the turret "forward facing" position. But the concept of how to do that eludes me.
Because as soon as turret rotates just a bit from limit, it's able to turn "towards" player again, and gets stuck at limit again.
Edited with the clarification in mind.
You need a function that will tell you if you should rotate clockwise or counter-clockwise, based on the enemy location.
First find the mid point, this will be:
var mid = (minYaw + maxYaw) / 2
In your example this will be 3 o'clock, straight right.
Now, if your current rotation is lower than mid, and the target is higher than mid, than you must rotate clockwise even if it's not the shortest rotation to get there.
If the target rotation is higher than mid, and the target is lower than mid, you must rotate counter-clockwise for the same reason. You may need to adjust for negative degrees.
Please note that this will create a secondary effect, where once the ship passes the half point of the dead zone (say moving from 10 o'clock to 8 o'clock in your example), the turret will start moving as if anticipating the flank. You may want to disable this movement in a special case.
I'll keep the second part of my answer as-is, for future references.
If you want it to move gradually, you need to use deltaTime or fixedDeltaTime in case of a fixed update. You can define how fast it will move by adding a speed property. Try something like this:
void update () {
var playerTarget = GameObject.FindGameObjectWithTag("Player");
var chaseDirection = Quaternion.LookRotation(playerTarget.transform.position - transform.position);
var newYaw = Mathf.Clamp(chaseDirection.eulerAngles.y, minYaw, maxYaw);
var currentRotation = transform.eulerAngles;
var desiredRotation= currentRotation;
var desiredRotation.y = newYaw;
transform.eulerAngles = Vector3.RotateTowards(currentRotation, desiredRotation, Time.deltaTime * RotationSpeed, 0.0f);
}
I'm trying to calculate what angle to hit a pool ball and predict where ball will go to..
I thought target ball should move within a normal direction.. but it moves
on totally different direction
RaycastHit2D hit = Physics2D.CircleCast(cue.position, _radius, dir, 100f, ~(ignoreLayer));
if (hit.collider != null)
{
Debug.DrawRay(hit.collider.transform.position, -1f * hit.normal,
Color.green, Time.fixedDeltaTime);
}
Here is result:
Set velocity
rb.velocity = dir * force;
Result:
How to find exact move direction, Thanks
Edit:
I have tried Double Radius Casting this works only half way.. only when ray inside inner circle
I suppose this is just a limitation of the physics engine, which is optimized for speed and use in games, and is not so exact.
Trying this myself in a simple 2D scene, I found that if I set the friction to 0.01 and the bounciness to 1.0, it works the way I would expect. (in Unity 2020.1)
In the small sample scene I added, there is a ball aiming at another so that the resulting angle should be 45 degrees. And after setting the phyics-mat to the properties with friction 0.01 and bounciness 1.0, the resulting angle is as expected.
With the default-mat I get the same behaviour you described.
Did you forget to assign the physics materials?
Have you single-stepped to the point of contact and checked if the aiming is correct?
my sample project trying this
I'm making a 3D game. One feature I want is 'classic' bouncing projectiles where bullets etc richocet off of surfaces. The issue I'm having is that my code works fine on some surfaces but not others. I've recorded a 15 second video to illustrate:
You tube vid
In the example the normals on the walls to the left are facing -Z and facing Z to the right. The walls are identical models and their normals are all correctly pointing outwards. You can see that the shot correctly bounces off one set of walls but not the other.
The code I'm currently using in OnCollision() is:
transform.LookAt(Vector3.Reflect(transform.position - startPosition, contact.normal.normalised));
Where the Vector3 startPosition is assigned when first firing the projectile and on each bounce. The rest of the code is simple stuff which would have no effect on this issue apart perhaps from in FixedUpdate where I do this to propel the projectile forward:
rigidbody.AddForce(transform.forward * speed);
I've tried the following which all give identical results:
Vector3 velocity = transform.forward;
velocity = 2 * (Vector3.Dot(velocity, Vector3.Normalize(contact.normal))) * Vector3.Normalize(contact.normal) - velocity; //Following the formula v' = 2 * (v . n) * n - v
transform.LookAt(velocity);
transform.LookAt(Vector3.Reflect(rb.velocity, contact.normal));
transform.LookAt(Quaternion.AngleAxis(180, contact.normal) * transform.forward * -1);
I've also tried using the rigidbody but I'm not sure how to proceed there:
rigidbody.AddTorque(Vector3.Reflect(rigidbody.velocity, contact.normal.normalized),ForceMode.Impulse);
Any idea what could be going wrong? Thanks.
Just putting the answer in the right place to be used by people with the same problem.
Solution was to assign the Reflect to a Vector3 during the collision then in FixedUpdate use that vector in the rb.AddForce like:
target = Vector3.Reflect(transform.forward, contact.normal.normalized);
rb.AddForce(target.normalized * projSpeed);
So my friend and I are making some 2D game, we are using some custom character controller, so we are not using rigidbody2D. Now we have some sort of catapult which needs to eject the player in a projectile-motion style.
We've done it for the catapult which shoots the player straight up
In inspector you can decide how much units do you want player to jump and how much does it need to get to reach max height.
So here is the code for the catapult that shoots the player up.
float ejectInicialY = (jumpHeight - ( player.physics.gravity * Mathf.Pow(timeToReachMaxHeight, 2) / 2)) / timeToReachMaxHeight;
float ejectVelocityY = ejectInicialY + player.physics.gravity * Time.deltaTime;
player.physics.playerVelocity = new Vector2(ejectVelocityY, 0f);
I tried to apply the same formulas for the X coordinate, but it doesn't work well.
Any help would be greatly appreciated.
This is ultimately a physics problem.
You are calculating current velocities by determining the acceleration of the object. Acceleration of an object can be determined from the net force acting on the object (F) and the mass of the object (m) through the formula a = F / m. I highly recommend reading some explanations of projectile motion and understanding the meaning of the motion equations you are using.
Vertical Direction
For the vertical direction, the net vertical force during the jump (assuming no air drag, etc.) is player.physics.gravity. So you apply your motion formulas assuming a constant acceleration of player.physics.gravity, which you've seemed to have accomplished already.
Horizontal Direction
Becausegravity does not commonly act in the horizontal direction, the net horizontal force during the jump (assuming no air drag, etc.) is 0. So again you can apply your motion formulas, but this time using 0 as your acceleration. By doing this, you should realize that velocityX does not change (in the absence of net horizontal force). Therefore the X coordinate can be determined through (in pseudo-code) newPositionX = startPositionX + Time.deltaTime * velocityX