AddForce transform.forward does not work in 2D unity - 2d

GetComponent<Rigidbody2D>().AddForce(transform.forward * Time.deltaTime * forceGathered, ForceMode2D.Impulse);
does not make gameobject move in 2D Unity.
I would like to make force gameobject according to another game object's rotation direction.

GetComponent() requires a parameter, in your case Rigidbody2D, so it should be like this:
GetComponent(typeof(Rigidbody2D)).AddForce(transform.forward * Time.deltaTime * forceGathered, ForceMode2D.Impulse);
...and the shorter version would be:
GetComponent<Rigidbody2D>().AddForce(transform.forward * Time.deltaTime * forceGathered, ForceMode2D.Impulse);
Also, I would recommended you to cache the Rigidbody2D component as it can get very expensive to use GetComponent() every time you need to access it.
It would be better to cache it on start:
Rigidbody2D rg;
void Start(){
rg = GetComponent<Rigidbody2D>();
}
void YourMovementFunction(){
if (!rg) return;
rg.AddForce(transform.forward * Time.deltaTime * forceGathered, ForceMode2D.Impulse);
}

Related

Calculating gravity velocity over a given distance and time

I'll just start by saying I'm looking at the "projectile" code found in the game "Runescape" originally wrote in Javascript. The original code can be found somewhere half way down the page of this link https://github.com/zg/317-client titled "Projectile". Ultimately what it does is track an object a move towards it at a certain speed relative to the targets distance and the amount of ticks left. The reason I'm racking my brains on this, originally was because of the tan function for the direction of the velocity, but now I'm trying to figure out part of an equation used in calculating the up and downwards force.
I've translated a basic form of this code to Unity in C# to try and reverse engineer it.
void Update()
{
if(x >= distance)
{
x = 0;
z = 0;
duration = 20;
velocityX = 0; velocityZ = 0; acceleration = 0f;
mobile = false;
target();
}
sim();
duration-= interval;
}
void target()
{
velocityX = distance / duration;
if (!mobile) {
velocityZ = -velocityX * Mathf.Tan(elevationPitch * 0.02454369f);
}
}
void sim()
{
acceleration = 2f * (- z - velocityZ * duration) / (duration * duration);
mobile = true;
x += velocityX * interval;
z += velocityZ * interval + 0.5f * acceleration * interval * interval;
velocityZ += acceleration * interval;
cube.transform.position = new Vector3(x,z,0);
}
}
I understand how the velocity addition works in regard to interval, and that velocityX is set to move along x distance linearly over a given duration. If I understand the tan function correctly also, it is used to determine the angle of trajectory and thus the direction of velocity.
In the past couple of days that I have been analyzing this, I was googling a lot about parabolic trajectory and anything related to this topic. I found that the 0.5f * acceleration * interval * interval is the formula for calculating distance and gravity - with the google image here...
enter image description here
Now what I really don't understand is the acceleration formula :
acceleration = 2f * (- z - velocityZ * duration) / (duration * duration);
Does this look familiar to anyone? or can you figure out the maths behind it? I basically was hoping someone could explain this to me. I would also say that I don't fully understand the gravity formula use in this code, it looks like acceleration is being used in place of gravity.
Thanks for your time, guys!

nvd3 scatterplot: labels on bullets

I have a requirement that the bullets on a specific implementation of a scatterplot needs to have labels next to them, however, it is known that many of the datapoints in the set are identical or very close to one another, so if I were to set labels on a fixed coordinate relative to the bullet, the labels would stack on top of eachother and not be readable.
I want to implement this so that the labels will give way for eachother - moving around, so they don't overlap - and I am thinking that this is a common enough idea that some approach already exists, but I have no idea what to search for. Does this concept have a name?
I would ofcource appreciate an implementation example, but that is not the most important thing. I am sure I can solve it myself, but I'd rather not reinvent something that someone else has already done better.
The image above displays examples of bullets on top of and close to each other
I ended up finding inspiration in Simulated Annealing.
My solution looks like this
/**
* Implements an algorithm for placing labels on a chart in a way so that they
* do not overlap as much.
* The approach is inspired by Simulated Annealing
* (https://en.wikipedia.org/wiki/Simulated_annealing)
*/
export class Placer {
private knownPositions: Coordinate[];
private START_RADIUS = 20;
private RUNS = 15;
private ORIGIN_WEIGHT = 2;
constructor() {
this.knownPositions = []
}
/**
* Get a good spot to place the object.
*
* Given a start coordinate, this method tries to find the best place
* that is close to that point but not too close to other known points.
*
* #param {Coordinate} coordinate
* #returns {Coordinate}
*/
getPlacement(coordinate: Coordinate) : Coordinate {
let radius = this.START_RADIUS;
let lastPosition = coordinate;
let lastScore = 0;
while (radius > 0) {
const newPosition = this.getRandomPosition(coordinate, radius);
const newScore = this.getScore(newPosition, coordinate);
if (newScore > lastScore) {
lastPosition = newPosition;
lastScore = newScore;
}
radius -= this.START_RADIUS / this.RUNS;
}
this.knownPositions.push(lastPosition);
return lastPosition;
}
/**
* Return a random point on the radius around the position
*
* #param {Coordinate} position Center point
* #param {number} radius Distance from `position` to find a point
* #returns {Coordinate} A random point `radius` distance away from
* `position`
*/
private getRandomPosition(position: Coordinate, radius:number) : Coordinate {
const randomRotation = radians(Math.random() * 360);
const xOffset = Math.cos(randomRotation) * radius;
const yOffset = Math.sin(randomRotation) * radius;
return {
x: position.x + xOffset,
y: position.y + yOffset,
}
}
/**
* Returns a number score of a position. The further away it is from any
* other known point, the better the score (bigger number), however, it
* suffers a subtraction in score the further away it gets from its origin
* point.
*
* #param {Coordinate} position The position to score
* #param {Coordinate} origin The initial position before looking for
* better ones
* #returns {number} The representation of the score
*/
private getScore(position: Coordinate, origin: Coordinate) : number {
let closest: number = null;
this.knownPositions.forEach((knownPosition) => {
const distance = Math.abs(Math.sqrt(
Math.pow(knownPosition.x - position.x, 2) +
Math.pow(knownPosition.y - position.y, 2)
));
if (closest === null || distance < closest) {
closest = distance;
}
});
const distancetoOrigin = Math.abs(Math.sqrt(
Math.pow(origin.x - position.x, 2) +
Math.pow(origin.y - position.y, 2)
));
return closest - (distancetoOrigin / this.ORIGIN_WEIGHT);
}
}
There is room for improvement in the getScore method, but the results are good enough for my case.
Basically, all points try to move to a random position in a given radius and sees if that position is "better" than the original. The algorithm keeps doing that for a smaller and smaller radius until radius = 0.
The class keeps track of all known points, so that when you try to place point number two, the scoring can account for the presence of point number one.

Calculating bank angle between two objects

I have a drone following a path for movement. That is, it doesn't use a rigidbody so I don't have access to velocity or magnitude and such. It follows the path just fine, but I would like to add banking to it when it turns left or right. I use a dummy object in front of the drone, thinking I could calculate the bank/tilt amount using the transform vectors from the two objects.
I've been working on this for days as I don't have a lot of math skills. Basically I've been copying pieces of code trying to get things to work. Nothing I do works to make the drone bank. The following code manages to spin (not bank).
// Update is called once per frame
void Update () {
Quaternion rotation = Quaternion.identity;
Vector3 dir = (dummyObject.transform.position - this.transform.position).normalized;
float angle = Vector3.Angle( dir, transform.up );
float rollAngle = CalculateRollAngle(angle);
rotation.SetLookRotation(dir, transform.right);// + rollIntensity * smoothRoll * right);
rotation *= Quaternion.Euler(new Vector3(0, 0, rollAngle));
transform.rotation = rotation;
}
/// <summary>
/// Calculates Roll and smoothes it (to compensates for non C2 continuous control points algorithm) /// </summary>
/// <returns>The roll angle.</returns>
/// <param name="rollFactor">Roll factor.</param>
float CalculateRollAngle(float rollFactor)
{
smoothRoll = Mathf.Lerp(smoothRoll, rollFactor, rollSmoothing * Time.deltaTime);
float angle = Mathf.Atan2(1, smoothRoll * rollIntensity);
angle *= Mathf.Rad2Deg;
angle -= 90;
TurnRollAngle = angle;
angle += RollOffset;
return angle;
}
Assuming you have waypoints the drone is following, you should figure out the angle between the last two (i.e. your "now-facing" and "will be facing" directions). The easy way is to use Vector2.Angle.
I would use this angle to determine the amount I'll tilt the drone's body: the sharper the turn, the harder the banking. I would use a ratio value (public initially so I can manipulate it from the editor).
Next, instead of doing any math I would rely on the engine to do the rotation for me - so I would go for Transform.Rotate function.In case banking can go too high and look silly, I would set a maximum for that and Clamp my calculated banking angle between zero and max.
Without knowing exactly what you do and how, it's not easy to give perfect code, but for a better understand of the above, here's some (untested, i.e. pseudo) code for the solution I visualize:
public float turnSpeed = 7.0f; //the drone will "rotate toward the new waypoint" by this speed
//bankSpeed+turnBankRatio must be two times "faster" (and/or smaller degree) than turning, see details in 'EDIT' as of why:
public float bankSpeed = 14.0f; //banking speed
public float turnBankRatio = .5f; //90 degree turn == 45 degree banking
private float turnAngle = 0.0f; //this is the 'x' degree turning angle we'll "Lerp"
private float turnAngleABS = 0.0f; //same as turnAngle but it's an absolute value. Storing to avoid Mathf.Abs() in Update()!
private float bankAngle = 0.0f; //banking degree
private bool isTurning = false; //are we turning right now?
//when the action is fired for the drone it should go for the next waypoint, call this guy
private void TurningTrigger() {
//remove this line after testing, it's some extra safety
if (isTurning) { Debug.LogError("oups! must not be possible!"); return; }
Vector2 droneOLD2DAngle = GetGO2DPos(transform.position);
//do the code you do for the turning/rotation of drone here!
//or use the next waypoint's .position as the new angle if you are OK
//with the snippet doing the turning for you along with banking. then:
Vector2 droneNEW2DAngle = GetGO2DPos(transform.position);
turnAngle = Vector2.Angle(droneOLD2DAngle, droneNEW2DAngle); //turn degree
turnAngleABS = Mathf.Abs(turnAngle); //avoiding Mathf.Abs() in Update()
bankAngle = turnAngle * turnBankRatio; //bank angle
//you can remove this after testing. This is to make sure banking can
//do a full run before the drone hits the next waypoint!
if ((turnAngle * turnSpeed) < (bankAngle * bankSpeed)) {
Debug.LogError("Banking degree too high, or banking speed too low to complete maneuver!");
}
//you can clamp or set turnAngle based on a min/max here
isTurning = true; //all values were set, turning and banking can start!
}
//get 2D position of a GO (simplified)
private Vector2 GetGO2DPos(Vector3 worldPos) {
return new Vector2(worldPos.x, worldPos.z);
}
private void Update() {
if (isTurning) {
//assuming the drone is banking to the "side" and "side" only
transform.Rotate(0, 0, bankAngle * time.deltaTime * bankSpeed, Space.Self); //banking
//if the drone is facing the next waypoint already, set
//isTurning to false
} else if (turnAngleABS > 0.0f) {
//reset back to original position (with same speed as above)
//at least "normal speed" is a must, otherwise drone might hit the
//next waypoint before the banking reset can finish!
float bankAngle_delta = bankAngle * time.deltaTime * bankSpeed;
transform.Rotate(0, 0, -1 * bankAngle_delta, Space.Self);
turnAngleABS -= (bankAngle_delta > 0.0f) &#63 bankAngle_delta : -1 * bankAngle_delta;
}
//the banking was probably not set back to exactly 0, as time.deltaTime
//is not a fixed value. if this happened and looks ugly, reset
//drone's "z" to Quaternion.identity.z. if it also looks ugly,
//you need to test if you don't """over bank""" in the above code
//by comparing bankAngle_delta + 'calculated banking angle' against
//the identity.z value, and reset bankAngle_delta if it's too high/low.
//when you are done, your turning animation is over, so:
}
Again, this code might not perfectly fit your needs (or compile :P), so focus on the idea and the approach, not the code itself. Sorry for not being able right now to put something together and test myself - but I hope I helped. Cheers!
EDIT: Instead of a wall of text I tried to answer your question in code (still not perfect, but goal is not doing the job, but to help with some snippets and ideas :)
So. Basically, what you have is a distance and "angle" between two waypoints. This distance and your drone's flight/walk/whatever speed (which I don't know) is the maximum amount of time available for:
1. Turning, so the drone will face in the new direction
2. Banking to the side, and back to zero/"normal"
As there's two times more action on banking side, it either has to be done faster (bankSpeed), or in a smaller angle (turnBankRatio), or both, depending on what looks nice and feels real, what your preference is, etc. So it's 100% subjective. It's also your call if the drone turns+banks quickly and approaches toward the next waypoint, or does things in slow pace and turns just a little if has a lot of time/distance and does things fast only if it has to.
As of isTurning:
You set it to true when the drone reached a waypoint and heads out to the next one AND the variables to (turn and) bank were set properly. When you set it to false? It's up to you, but the goal is to do so when the maneuver is finished (this was buggy in the snippet the first time as this "optimal status" was not possible to ever be reached) so he drone can "reset banking".For further details on what's going on, see code comments.Again, this is just a snippet to support you with a possible solution for your problem. Give it some time and understand what's going on. It really is easy, you just need some time to cope ;)Hope this helps! Enjoy and cheers! :)

Find lead to hit a moving target considering gravity in 3D

I'm trying to find a point in 3D space at which I'd have to aim in order to hit a moving target with a projectile which is affected by gravity.
To give you a better picture: imagine an anti-aircraft gun trying to hit an aircraft flying above.
We can assume that the target and the projectile move at a constant rate, other than gravity in the case of the projectile. We can also assume that the shooter is stationary, since if he's not we can just use relative speeds.
After some research I found this article.
I was able to implement his first solution, since he was so kind to give a code example. That looks like this:
public static Vector3 CalculateLead(Vector3 targetVelocity, Vector3 targetPosition, Vector3 gunPosition, float projectileSpeed)
{
Vector3 direction = targetPosition - gunPosition;
float a = targetVelocity.sqrMagnitude - projectileSpeed * projectileSpeed;
float b = 2 * Vector3.Dot(direction, targetVelocity);
float c = direction.sqrMagnitude;
if (a >= 0)
return targetPosition;
else
{
float rt = Mathf.Sqrt(b * b - 4 * a * c);
float dt1 = (-b + rt) / (2 * a);
float dt2 = (-b - rt) / (2 * a);
float dt = (dt1 > 0 ? dt1 : dt2);
return targetPosition + targetVelocity * dt;
}
}
With this code I'm able to perfectly hit the target, as long as the projectile isn't affected by gravity. However, I'd like it to be. Unfortunately I'm not even remotely close to understanding the math posted in the article so I wasn't able to translate it into working code. And after spending several hours trying to find a solution which includes gravity I figured I'd just ask you guys for help.

How to rotate MXML component round its center like a wheel respectfully to mouse?

So I have that panel or any other mxml component. I want somehow to rotate it around like a wheel of a car with which you drive it... loke a Racing wheel... sow like when mousebutton is down it captures pont of component... when you move mouse component rotates (not moves) according to new mouse position... How to rotate MXML component round its center like a wheel respectfully to mouse?
welll feel free to edit this question because I know Ive formulated it in a bad way...
Add these to a utility class if you don't want to add a dependency to fl.motion.*
/**
* Rotates a matrix about a point defined inside the matrix's transformation space.
* This can be used to rotate a movie clip around a transformation point inside itself.
*
* #param m A Matrix instance.
*
* #param x The x coordinate of the point.
*
* #param y The y coordinate of the point.
*
* #param angleDegrees The angle of rotation in degrees.
* #playerversion Flash 9.0.28.0
* #langversion 3.0
* #keyword Matrix, Copy Motion as ActionScript
* #see flash.geom.Matrix
*/
public static function rotateAroundInternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void
{
var point:Point = new Point(x, y);
point = m.transformPoint(point);
m.tx -= point.x;
m.ty -= point.y;
m.rotate(angleDegrees*(Math.PI/180));
m.tx += point.x;
m.ty += point.y;
}
/**
* Rotates a matrix about a point defined outside the matrix's transformation space.
* This can be used to rotate a movie clip around a transformation point in its parent.
*
* #param m A Matrix instance.
*
* #param x The x coordinate of the point.
*
* #param y The y coordinate of the point.
*
* #param angleDegrees The angle of rotation in degrees.
* #playerversion Flash 9.0.28.0
* #langversion 3.0
* #keyword Matrix, Copy Motion as ActionScript
* #see flash.geom.Matrix
*/
public static function rotateAroundExternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void
{
m.tx -= x;
m.ty -= y;
m.rotate(angleDegrees*(Math.PI/180));
m.tx += x;
m.ty += y;
}
They are MatrixTransformer's rotateAroundInternalPoint() and rotateAroundExternalPoint()
That would be for 2d. For 3d see transformAround.
Don't forget to check if layout siblings are updated properly or not.
HTH
I believe you can rotate the component using the rotateX, rotateY, and rotateZ properties:
http://docs.huihoo.com/flex/4/mx/core/UIComponent.html#rotationX
Just make that happen in response to a mouse click.

Resources