acceleration-field for unity3D racing game, c# - unity3d

for a motorcycle racing game I want some parts of the track to increase the speed of the motorcycle.
I have a public float for the speed, which shows the speed in the inspector.
I added a plane with a Collider, which is a trigger and has the tag "speedfield"
Now I thought, some simple code, attached to the motorcyclescript below, would do it:
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("speedfield")) {
Speed = Speed + 50;
}
}
But nothing happens. I think I'm missing something obvious here. Hope you can help! Greetings from germany :)
void FixedUpdate (){
Inputs();
Engine();
}
void Inputs (){
Speed = rigid.velocity.magnitude * 3.6f;
//Freezing rotation by Z axis.
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0);
//If crashed...
if(!crashed){
if(!changingGear)
motorInput = Input.GetAxis("Vertical");
else
motorInput = Mathf.Clamp(Input.GetAxis("Vertical"), -1, 0);
steerInput = Input.GetAxis("Horizontal");
}else{
motorInput = 0;
steerInput = 0;
}
//Reverse bool
if(motorInput < 0 && transform.InverseTransformDirection(rigid.velocity).z < 0)
reversing = true;
else
reversing = false;
}
void Engine (){
//Steer Limit.
SteerAngle = Mathf.Lerp(defsteerAngle, highSpeedSteerAngle, (Speed / highSpeedSteerAngleAtSpeed));
FrontWheelCollider.steerAngle = SteerAngle * steerInput;
//Engine RPM.
EngineRPM = Mathf.Clamp((((Mathf.Abs((FrontWheelCollider.rpm + RearWheelCollider.rpm)) * gearShiftRate) + MinEngineRPM)) / (currentGear + 1), MinEngineRPM, MaxEngineRPM);
// Applying Motor Torque.
if(Speed > maxSpeed){
RearWheelCollider.motorTorque = 0;
}else if(!reversing && !changingGear){
RearWheelCollider.motorTorque = EngineTorque * Mathf.Clamp(motorInput, 0f, 1f) * engineTorqueCurve[currentGear].Evaluate(Speed);
}
if(reversing){
if(Speed < 10){
RearWheelCollider.motorTorque = (EngineTorque * motorInput) / 5f;
}else{
RearWheelCollider.motorTorque = 0;
}
}
}

You overriding speed variable:
void FixedUpdate (){
Inputs();
Engine();
}
void Inputs (){
Speed = rigid.velocity.magnitude * 3.6f;
...
}
change it to:
[SerializeField] float speedMultiplier = 3.6f;
[SerializeField] float speedMultiplierChange = 2;
void Inputs (){
Speed = rigid.velocity.magnitude * speedMultiplier;
...
}
and
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("speedfield")) {
speedMultiplier += speedMultiplierChange;
}
}

Make sure that all items in this checklist are satisfied:
The motorcycle has a Rigidbody component.
The plane doesn't have a Rigidbody component (it's useless and it could slow things down).
The Mesh Collider of the plane has Convex and isTrigger set to true.
The OnTriggerEnter method is in the motorcycle script.
The thickness of the plane trigger is wide enough: if the motorcycle speed is too high, it can pass thru the plane without the physics engine being able to register the trigger.
If this is the case, try to set the Collision Detection of the motorcycle Rigidbody to Continuous and/or decrease somewhat the Fixed Timestep in the Time project settings.
Most probably the problem is due to the last two bullet points.

Related

Unity3D 2D Simple Flight Physics

I want to create a simple flight physics sim, arcade-y like game, in 2D.
I don't want something too realistic, just something fun.
Unfortunately, my code leads to a game, where my plane acts more like a missile in space, than an aerodynamic plane.
I've checked for questions around the internet, the closest one I found was this.
Which the guy wrote about this game.
The game looks a bit like what I want to do.
I couldn't find any practical code I can use to make my plane more realistic, so I'm looking for help.
Please, do not send me to learn aerodynamics or to something not useful, I do have a simple understanding, and I would like some practical help, not theoretical one.
The main issue I have, is when I want to pitch up/down the plane, the plane just rotates itself with the Torque force, however, it doesn't change it's direction quickly with the air flow (since there's no 'real' air flow...)
I've tried playing with the rigidbody drag, and angular drag, and the parameters, I've added a drag force of my own... I am missing something and I don't know what. I was also looking at these formulas, I didn't find the solution.
Thanks in advance,
Here is my code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlaneController : MonoBehaviour {
public float thrustFactor = 0.01f;
public float maxThrustFactor = 1.0f;
public float liftFactor = 0.1f;
public float turnFactor = 0.1f;
public float gravityFactor = 0.1f;
public float dragFactor = 0.1f;
public float thrust;
public float liftForce;
private Vector2 planeVelocity;
private Rigidbody2D transformRigidbody;
// Use this for initialization
void Start () {
thrust = 0;
liftForce = 0;
transformRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate () {
planeVelocity = transformRigidbody.velocity;
PlaneGravity();
PlaneThrust();
PlaneDrag();
PlaneTurn();
PlaneLift();
}
void PlaneLift()
{
float attackAngle = transform.eulerAngles.z;
if ((attackAngle > 0 && attackAngle <= 45) || (attackAngle > 90 && attackAngle <= 135))
liftForce = Mathf.Sin(attackAngle) * liftFactor * planeVelocity.sqrMagnitude;
else if ((attackAngle > 45 && attackAngle <= 90) || (attackAngle > 135 && attackAngle <= 180))
liftForce = Mathf.Cos(attackAngle) * liftFactor * planeVelocity.sqrMagnitude;
transformRigidbody.AddForce(Vector2.up * Mathf.Abs(liftForce) * Time.fixedDeltaTime);
}
void PlaneThrust()
{
if (Input.GetKey("w"))
{
thrust += thrustFactor;
thrust = Mathf.Min(thrust, maxThrustFactor);
}
if (Input.GetKey("s"))
{
thrust -= thrustFactor;
thrust = Mathf.Max(0, thrust);
}
transformRigidbody.AddForce(transform.right * thrust * Time.fixedDeltaTime);
}
void PlaneGravity()
{
transformRigidbody.AddForce(gravityFactor * Vector2.down * Time.fixedDeltaTime);
}
void PlaneDrag()
{
transformRigidbody.AddForce(-transform.right * planeVelocity.sqrMagnitude * Time.fixedDeltaTime);
}
void PlaneTurn()
{
if (Input.GetKey("up"))
{
transformRigidbody.AddTorque(-turnFactor * Mathf.Abs(planeVelocity.sqrMagnitude) * Time.fixedDeltaTime);
}
if (Input.GetKey("down"))
{
transformRigidbody.AddTorque(turnFactor * Mathf.Abs(planeVelocity.sqrMagnitude) * Time.fixedDeltaTime);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
Vector3 newPosition = transform.position;
if (other.name == "LeftCollider")
{
newPosition.x += 17;
}
if (other.name == "RightCollider")
{
newPosition.x -= 17;
}
transform.SetPositionAndRotation(newPosition, transform.rotation);
}
private void OnCollisionExit2D(Collision2D collision)
{
if(collision.transform.name == "Ground")
{
transformRigidbody.freezeRotation = false;
}
}
}

How can i get the movement of an object to follow the y co-ordinate movement of another game object

I'm trying to program AI for a pong game and i'm trying to make the paddle game object follow the y co-ordinate movement of the ball game object.
The problem is that the paddle ends up just moving up and down and not actually following the ball.
This is the script i used to make it follow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AIMove : MonoBehaviour {
public int speed;
public bool validUp = true;
public bool validDown = true;
void Awake()
{
}
void Update()
{
GameObject sphere = GameObject.Find("Sphere");
Transform spherePosition = sphere.GetComponent<Transform>();
float spherePos = spherePosition.position.y;
if (spherePos < (0) && validUp == (true))
{
transform.Translate(Vector3.up * speed * Time.deltaTime);
}
else if (spherePos > (0) && validDown == (true))
{
transform.Translate(Vector3.down * speed * Time.deltaTime);
}
if (transform.position.y >= (2.3F))
{
validUp = false;
}
else if (transform.position.y <= (-2.3F))
{
validDown = false;
}
else
{
validUp = true;
validDown = true;
}
}
}
I think you do not fully understand how your code works. Let's take a look inside your Update method.
if (spherePos < (0) && validUp == (true))
{
transform.Translate(Vector3.up * speed * Time.deltaTime);
}
What you are saying here is that if the position of the sphere on the Y axis is below 0, the AI paddle should move up. This contains no condition on whether the sphere is moving upwards or downwards. So, the sphere could be moving downwards, and you would still be moving the AI paddle upwards.
else if (spherePos > (0) && validDown == (true))
{
transform.Translate(Vector3.down * speed * Time.deltaTime);
}
This contains the same kind of problems.
Instead, you could do something like this.
[SerializeField]
private float speed;
private Transform sphere;
private void Start()
{
// In general, I'd recommend avoiding
// GameObject.Find, but we'll use it for now.
sphere = GameObject.Find("Sphere").transform;
}
private void Update()
{
if(sphere.position.y >= transform.position.y)
{
transform.Translate(Vector.up * speed * Time.deltaTime);
}
else if(sphere.position.y <= transform.position.y)
{
transform.Translate(Vector.down * speed * Time.deltatime);
}
}
This would basically compare the paddle's position on the Y axis to the sphere's position on the Y axis and move the paddle accordingly, to the correct direction. Then you just have to adjust the speed value as you want.
Note that this only moves the paddle based on the sphere's position on the Y axis alone. It does not take into account how the sphere is going to bounce off the walls or anything like that.

How to prevent tilting over in a unity object

I've got a hover tank and I'm working on a controller for it. The goal is to have the float above the ground, but I don't want it to tilt over more the a degree or two. I want it to basically stay level all the time.
I'm using a Rigidbody on the tank to control it with .MovePosition and .MoveRotation. You can see the FixedUpdate function below. I've got a section below to keep thinks level, where I check if there tank is tipping past its maxTilt amount. If it is, the keep it at the max.
This makes the tank very jittery all the time. It looks like it's bouncing up and down quickly. I think its due to the hover forces, but I'm not sure.
How can I keep the tank level while still letting it hoover?
FixedUdpate
void FixedUpdate () {
if (!isServer) {
return;
}
CheckGrounded ();
Hoover ();
if (_moveForward) {
float moveAmount = moveSpeed * Time.deltaTime;
_rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
}
if (_moveBackward) {
float moveAmount = (-moveSpeed * 0.6f) * Time.deltaTime;
_rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
}
if (_turnLeft) {
Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, -angularSpeed, 0f) * Time.deltaTime);
_rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
}
if (_turnRight) {
Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, angularSpeed, 0f) * Time.deltaTime);
_rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
}
if (_jump && _isGrounded) {
_isJumping = true;
}
if (_isJumping && _jumpTimeLeft > 0) {
float moveAmount = jumpSpeed * Time.deltaTime;
_rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.up * moveAmount);
_jumpTimeLeft -= Time.deltaTime;
} else if (_isJumping) {
_isJumping = false;
_jumpTimeLeft = jumpTime;
}
// Keep things level
Vector3 rotation = _rigidbody.rotation.eulerAngles;
if (rotation.x > maxTilt) {
rotation.x = maxTilt;
} else if (rotation.x < -maxTilt) {
rotation.x = -maxTilt;
}
if (rotation.y > maxTilt) {
rotation.y = maxTilt;
} else if (rotation.y < -maxTilt) {
rotation.y = -maxTilt;
}
if (rotation.z > maxTilt) {
rotation.z = maxTilt;
} else if (rotation.z < -maxTilt) {
rotation.z = -maxTilt;
}
Quaternion q = new Quaternion ();
q.eulerAngles = rotation;
_rigidbody.rotation = q;
}
Hoover
void Hoover() {
foreach (Transform hoverPoint in hooverPoints) {
Ray ray = new Ray (hoverPoint.position, -hoverPoint.up);
RaycastHit hitInfo;
if (Physics.Raycast (ray, out hitInfo, hooverHeight)) {
float distance = Vector3.Distance (hoverPoint.position, hitInfo.point);
if (distance < hooverHeight) {
_rigidbody.AddForceAtPosition (hoverPoint.up * hooverForce * (1f - distance / hooverHeight), hoverPoint.position, ForceMode.Force);
}
}
}
}
I'm thinking that the reason you are seeing 'jitters' is because...
All physics calculations and updates occur immediately after FixedUpdate.
https://docs.unity3d.com/Manual/ExecutionOrder.html
Because you are adjusting the tilt in FixedUpdate(), which is then immediately followed by the Physics Engine running its calculations this will sometimes alter the tilt value giving a 'jitter'. The reason I say sometimes is because FixedUpdate() can run multiple times per frame (FPS dependant), which potentially means the following call order for a single frame:
FixedUpdate() // start frame
PhysicsEngine
FixedUpdate() // end frame
In the case above, there would be no jitter because you re-correct the tilt after the physics engine has done its thing - by complete fluke. However when you don't get a second FixedUpdate() call on a frame, you will have:
FixedUpdate() // start frame
PhysicsEngine // end frame
Which will result in your jitter.
So my suggestion is to break up your FixedUpdate() and offset any tilt corrections to LateUpdate(). Becuase LateUpdate() is always the last update call prior to the rendering of the frame.

Unity3D How to make object go away form mouse click position 2D

Im thinking about it two days. I still did not made any progress.
I wonder how to do that objects fly away from mouse click position in 2D view?
I tried like that:
pos = Input.mousePosition;
Vector3 realWorldPos = Camera.main.ScreenToViewportPoint(pos);
print("MOuse pos: " + realWorldPos);
//print(realWorldPos);
Vector3 velo = GetComponent<Rigidbody2D>().velocity;
if (realWorldPos.x < 0.5)
{
velo = new Vector3((realWorldPos.x * speed), velo.y);
}
else if(realWorldPos.x > 0.5)
{
velo = new Vector3((realWorldPos.x * speed) * (-1), velo.y);
}
if (realWorldPos.y < 0.5)
{
velo = new Vector3(velo.x, realWorldPos.y * speed);
}
else if (realWorldPos.y > 0.5)
{
velo = new Vector3(velo.x, (realWorldPos.y * speed) * (-1));
}
GetComponent<Rigidbody2D>().velocity = velo;
But it doesnt work as I want.
Is it possible to do this?
For this to work your Rigidbody2D must have Gravity Scale set to 0.
This is a simple test code that works for me, is placed on a sprite object:
public class PushPlayer : MonoBehaviour
{
public float pushPower = 50.0f;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Vector3 dir = transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition);
dir = dir.normalized;
rb.AddForce(dir * pushPower, ForceMode2D.Force);
// as alternative:
rb.velocity = dir * pushPower;
}
}
}
You need to adjust the values a bit, also in the regidbody (like drag) to get it the way you want.
Edit:
transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition): calculate the directional vector from the mouse position to the player position (have a look a vector algebra if you are not familiar with this) which is the direction away from the click (in a straight line).
dir.normalized: this shortens the vector to a length (= magnitude) of 1 (again have a look at vectors) so it really is just a direction. You could omit this and reduce the factor, but doing it this way your factor equals the force you use.

object movement as wave in Unity 3d

I created a object in unity
GameObject monsterclone =
(GameObject)Instantiate(monsterPrefab, floorPosition, Quaternion.identity);
This object should move in a wave style from a limit1 to limit2.
Then move back from limit2 to limit1.
Y position as well x position have to change in a specific way.
Vector3 nPos = mfloorPos + new Vector3(2f, 0f, 0f);
Vector3 oPos = mfloorPos + new Vector3(-2f, 0f, 0f);
How can I do it?
I can't exactly write the code without knowing more specific but i think this question is already asked any this link will help you out MOVE OBJECT as wave
EDIT:
I think the flat up and float down functionality will work for you for moving one point to another
example:
var floatup;
function Start(){
floatup = false;
}
function Update(){
if(floatup)
floatingup();
else if(!floatup)
floatingdown();
}
function floatingup(){
transform.position.y += 0.3 * Time.deltaTime;
yield WaitForSeconds(1);
floatup = false;
}
function floatingdown(){
transform.position.y -= 0.3 * Time.deltaTime;;
yield WaitForSeconds(1);
floatup = true;
}
example taken from
float amplitudeX = -25.0f;
float amplitudeY = 5.0f;
float omegaX = 0.5f;
float omegaY = 4.0f;
float index;
void Update () {
index += Time.deltaTime;
float x = amplitudeX*Mathf.Cos (omegaX*index);
float y = Mathf.Abs (amplitudeY*Mathf.Sin (omegaY*index));
if(transform.position.x > 24){
transform.eulerAngles = new Vector3(270, -90, 0);
}
if(transform.position.x < -24){
transform.eulerAngles = new Vector3(270, 90, 0);
}
transform.localPosition= new Vector3(x,y,20);
}
If this is a consitant wave and not dependant on speed I would use an animation to create a literal wave curve of the Position.Y value (much in the same principle as Ravindra Shekhawat has explained.) you can find out more about animation here.
Here is some code (untested) that you could go off. It is in c# so I hope it proves no issue with putting in to JavaScript.
bool monsterMoving = false;
void Update(){
//check monster moving to start updating position
if(monsterMoving == true){
//moving animation controls up and down "wave" movement
animation.CrossFade('moving');
//Lerp changes position
Transform.Lerp(transform.Position, oPos, Time.deltaTime);
if (transform.Position == oPos) {
//We are at destination, stop movement
monsterMoving = false;
}
} else {
// if monster stopped moving, return to idle animation (staying still)
animation.CrossFade('idle');
}
}
// function to send a new position to the monster object
void MoveTo(Vector3 newPos){
oPos = newPos;
monsterMoving = true;
}