Make a Tank Aim Properly - c#

Hi I am trying to make my tank fire, but it doesn't seem to work.
My tank's gun has a firing point which is used to fire the object. FirePoint is the point from which the laser beam is instantiated. When I turn my turret though the point goes off. The point is a child of the gun turret. What do I need to do? If I haven't explained it enough, please ask and I will try my best to help.
This is my player controller script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float Speed = 0;
public float MaxSpeed;
public float TurnSpeed;
public float AccelRate = 1;
public float BrakeSpeed = 1;
public GameObject LaserBeam;
public GameObject FirePoint;
public Vector3 Offset;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Increase forward when up arrow pressed
if (Input.GetKey(KeyCode.UpArrow))
{
Speed = Speed + AccelRate;
}
// Move backward when down arrow pressed
if (Input.GetKey(KeyCode.DownArrow))
{
Speed = Speed - AccelRate;
}
// Turn when left arrow pressed
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(Vector3.down * Time.deltaTime * TurnSpeed);
}
// Turn when right arrow pressed
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(Vector3.up * Time.deltaTime * TurnSpeed);
}
// Reset vehicle rotation
if (Input.GetKey(KeyCode.Return))
{
transform.eulerAngles = new Vector3(0, 0, 0);
}
// Press the brakes
if (Input.GetKey(KeyCode.Space) && (Speed > 0 || Speed < 0))
{
Speed = Speed - BrakeSpeed;
if (Speed < 0) { Speed = 0; }
}
//Ensure vehicle does not pass the maxspeed
if (Speed > MaxSpeed)
{
Speed = MaxSpeed;
}
//Move vehicle
transform.Translate(Vector3.right * Time.deltaTime * Speed);
if (Input.GetKey(KeyCode.UpArrow) == false && Speed > 0)
{
Speed = Speed - AccelRate;
}
//Fire
if (Input.GetKeyDown(KeyCode.F))
{
Instantiate(LaserBeam, FirePoint.transform.position + Offset, FirePoint.transform.rotation);
}
}
}

I fixed it! I simply set the offset to 0,0,0 and it worked.

Related

unity c# issue unable to get perfect position of a enemy in unity c# script using transform.position

when I command or set an enemy to go left and then at reaching a particular state or position i say my enemy to go right but it is not going right and not reaching to perfect position here is the code I think there is no issue in the code but it is not working properly so here are some images of the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enem : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.position = transform.position + new Vector3(-3f, 0f, 0f)* 1 * Time.deltaTime;
if (transform.position.x > -29)
{
transform.position = transform.position + new Vector3(3f, 0f, 0f) * 1 * Time.deltaTime;
}
}
}
Before adding any bool logic, try first simply moving your element:
using UnityEngine;
public class SimeMoveMove : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
transform.position += new Vector3(3f, 0f, 0f);
}
}
}
I smiled a little the moment I understood what you were trying to do.
I wrote the code imagining the result you were trying to make!
Create a cube, attach this code as component, and run the game.
// Gift for you friend
public class MoveTest : MonoBehaviour
{
private int _direction = 1;
void Start()
{
transform.position = Vector3.zero;
}
void Update()
{
Vector3 position = transform.position;
int direction = ShouldWeSwitchDirection(position.x, 0f);
if (direction != 0)
{
_direction = direction;
}
transform.position += _direction * new Vector3(3f, 0f, 0f) * 3f * Time.deltaTime;
}
private int ShouldWeSwitchDirection(float value, float center = 0f)
{
float direction = Mathf.Sign(value - center);
float distance = Mathf.Abs(value - center);
// If X Position is larger than 29
if (Mathf.Abs(distance) > 29)
{
// If X is on right side
if (direction >= 0)
{
return -1;
}
// If X is on left side.
else
{
return 1;
}
}
else
{
return 0;
}
}
}

How do I disable diagonal movement in Unity 2D?

I would like to ask if there is a way to disable diagonal movement in Unity 2D.
The thing is when I press 'W' + 'D'(move key) at the same time then the character starts to move diagonally.
So instead of the character moving diagonal when combining button press, I want it to go completely straight instead if I press 'd' or any other key to move even if I'm still pressing the other button at the same time. So to say prioritize the function of the last button I pressed.
Here's a short video to explain my problem further .
https://youtu.be/aPZii5HfP4s
And here's the code for my character movement.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keycontrol : MonoBehaviour
{
public float moveSpeed = 0f;
public Rigidbody2D rb2d;
Vector2 movement;
public Animator animator;
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
animator.SetFloat("walk_right", movement.x);
animator.SetFloat("walk_left", -movement.x);
animator.SetFloat("walk_down", -movement.y);
animator.SetFloat("walk_up", movement.y);
}
void FixedUpdate()
{
rb2d.MovePosition(rb2d.position + movement * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 200 * Time.deltaTime;
animator.speed = 1.5f;
}
else
{
moveSpeed = 110 * Time.deltaTime;
animator.speed = 1f;
}
}
}
Thanks for help
A simple way to do this is to prioritize one axis over the other and just wrap the other check in a condition.
movement.x = Input.GetAxisRaw("Horizontal");
if (movement.x != 0)
{
movement.y = Input.GetAxisRaw("Vertical");
}
However, this can fail, because depending on your input, the axis might return values close to zero when using a controller. In this case, you could just get both values and check for the larger one.
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
if (Mathf.Abs(movement.x) > Mathf.Abs(movement.y))
{
movement.y = 0;
}
else
{
movement.x = 0;
}
Sharing as an answer since I can't comment on this post, you should check out the new input system unity released recently: https://docs.unity3d.com/Packages/com.unity.inputsystem#1.0/manual/QuickStartGuide.html
It gives better control over inputs such as event systems so you can lock the movement until the first key is released.
You can handle the movement only in one of the axis handled each chance in the code, find draft below:
bool isXMoving;
bool isYMoving;
// Update is called once per frame
void Update()
{
if (Input.GetAxisRaw("Horizontal") != 0f && !isYMoving) {
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = 0;
isXMoving = true;
isYMoving = false;
}
if (Input.GetAxisRaw("Horizontal") != 0f && !isXMoving) {
movement.y = Input.GetAxisRaw("Vertical");
movement.x = 0;
isYMoving = true;
isXMoving = false;
}
Debug.Log($"X: {movement.x} Y: {movement.y}"); //check
animator.SetFloat("walk_right", movement.x);
animator.SetFloat("walk_left", -movement.x);
animator.SetFloat("walk_down", -movement.y);
animator.SetFloat("walk_up", movement.y);
}
You can add condition to check if the horizontal movement is pressed.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keycontrol : MonoBehaviour
{
public float moveSpeed = 0f;
public Rigidbody2D rb2d;
Vector2 movement;
public Animator animator;
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
if(movement.x == 0){
movement.y = Input.GetAxisRaw("Vertical");
}
animator.SetFloat("walk_right", movement.x);
animator.SetFloat("walk_left", -movement.x);
animator.SetFloat("walk_down", -movement.y);
animator.SetFloat("walk_up", movement.y);
}
void FixedUpdate()
{
rb2d.MovePosition(rb2d.position + movement * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 200 * Time.deltaTime;
animator.speed = 1.5f;
}
else
{
moveSpeed = 110 * Time.deltaTime;
animator.speed = 1f;
}
}
}

How to Prevent sliding in 2d movement

hi i want to move my charachter i looked around but couldnt find solutions for my code i just want when my charachter moves and i not pressed move forward button then it stop but not instantly it just stops instantly after i unpressed d button here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public Rigidbody2D rb2d;
bool ismoving;
public float speed = 5f;
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
if (Input.GetButton("Horizontal"))
{
ismoving = true;
}
else { ismoving = false; }
if (ismoving)
{
rb2d.AddForce(new Vector2(horizontal, 0) * speed * Time.fixedDeltaTime *10);
}
else
{
while((rb2d.velocity) != (rb2d.velocity = Vector2.zero))
{
rb2d.AddForce(new Vector2(horizontal, 0) * Time.fixedDeltaTime *-1);
}
}
}
}
You can change the multiplier for your deceleration to a greater value
while((rb2d.velocity) != (rb2d.velocity = Vector2.zero))
{
rb2d.AddForce(new Vector2(horizontal, 0) * Time.fixedDeltaTime * -10);
}
Now it should decelerate 10 times faster than before
Currently, you stop adding force when the key is released. How about approaching a speed of 0 once the key is released? Like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public Rigidbody2D rb2d;
bool ismoving;
public float maxspeed = 5f;
private float currentSpeed = 0f;
private float movingDirection = 0f;
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
if (Input.GetButton("Horizontal"))
{
ismoving = true;
movingDirection = horizontal;
}
else
{
ismoving = false;
// keep the movingDirection as it is.
}
if (ismoving)
{
// accelerate
currentSpeed += 5 * Time.fixedDeltaTime;
currentSpeed = Mathf.Clamp(currentSpeed, 0, maxspeed);
}
else
{
currentSpeed -= 5 * Time.fixedDeltaTime;
currentSpeed = Mathf.Clamp(currentSpeed, 0, maxspeed);
// also fake some friction
rb2d.velocity = rb2d.velocity * 0.96f;
}
// always apply the force, it may be 0 though.
rb2d.AddForce(new Vector2(movingDirection, 0) * currentSpeed;
}
}
Maybe it works better when setting velocity instead of adding force with this approach. But you may get the point: Instead of instantly stopping to add force when the key is released, we simply decrease a variable currentspeed and continue to work with that until we stop. Since horizontal is getting 0 quickly after releasing the key, I added a helper variable to remember the direction we were going before releasing the key called movingDirection.
Also a nice-to-know tip: Try to do all Input... Calls in Update(), save states in variables that you then use in FixedUpdate(). Because otherwise, you may run into problems, when things like Input.GetButtonDown() is true for 2-3 FixedUpdate Calls, but you want things to happen once per click/press like shooting.

How can I change a bullet shooting speed and keep the bullet shooting distance using physics?

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEditor;
using UnityEngine;
public class ShootBullets : MonoBehaviour
{
public float bulletDistance;
public bool automaticFire = false;
public float fireRate;
public Rigidbody bullet;
private float gunheat;
private bool shoot = false;
private GameObject bulletsParent;
private GameObject[] startpos;
// Start is called before the first frame update
void Start()
{
bulletsParent = GameObject.Find("Bullets");
startpos = GameObject.FindGameObjectsWithTag("Pod_Weapon");
}
void Fire()
{
for (int i = 0; i < startpos.Length; i++)
{
Rigidbody bulletClone = (Rigidbody)Instantiate(bullet, startpos[i].transform.position, startpos[i].transform.rotation, bulletsParent.transform);
bulletClone.velocity = transform.forward * bulletDistance;
// The bullet or any ammo/weapon should be on Y rotation = 0
Destroy(bulletClone.gameObject, 0.5f);
}
}
// Update is called once per frame
void Update()
{
if (automaticFire == false)
{
if (Input.GetMouseButtonDown(0))
{
Fire();
}
}
else
{
if (shoot == true)
{
Fire();
shoot = false;
}
}
if (gunheat > 0) gunheat -= Time.deltaTime;
if (gunheat <= 0)
{
shoot = true;
gunheat = fireRate;
}
}
}
I want to keep the distance like in this line :
bulletClone.velocity = transform.forward * bulletDistance;
but also to control the bullet speed. maybe it's a problem when using physics ?
my problem is that the bullets shot too fast.
the question is if it's possible to control the speed and keep the distance using physics ?
and does the function Fire should be called from Update or FixedUpdate ?
I meant something different with "over lifetime" but it doesn't matter. The speed is currently only set once so it is only dependent on the distance you shot the bullet from. Not the distance left to the target.
If you want to keep distance in the equation but decrease the result, have you thought about dividing the speed? IE add something like this
bulletClone.velocity = transform.forward * bulletDistance / 3;
you can also compare the speed to a maximum value and decide on which to pick IE
if(bulletDistance < 30)
{
bulletClone.velocity = transform.forward * bulletDistance;
}
else
{
bulletClone.velocity = transform.forward * 30
}
You can set the speed to anything you want.

c# Unity Jump Issue

I'm new to programming in C#.
I have a sphere rigid body on a plane in unity.
I want to make this sphere jump when the spacebar is pressed and then bounce twice before coming to rest again when the key is released.
This will not always be on the plane it will sometimes be on an object and I would like the height of the bounce to reflect the distance dropped from the initial jump.
I currently have a camera facing onto the sphere from a side and have it following the ball from a set distance. The sphere can move in any direction but the camera always stays on the same side and distance from the sphere.
The issue is that my code currently says (to my knowledge) IF the spacebar is not pressed try to move the sphere's Y position down, then if the spacebar is pressed make the sphere jump and then come back down on spacebar release.
The way this code is written makes my plane jump as the ball is constantly bouncing into it when spacebar is not being pressed but if I take that part out the ball refuses to drop.
Example Code :
public class RollAdvancedScript : MonoBehaviour
{
public Transform camera;
public float posY;
void lol()
{
posY = transform.position.y;
}
void Update()
{
if (Input.GetKey(KeyCode.D))
{
Vector3 vectorToUse = camera.right;
vectorToUse.y = 0;
transform.position += vectorToUse * Time.deltaTime * 5;
}
if (Input.GetKey(KeyCode.A))
{
Vector3 vectorToUse = -camera.right;
vectorToUse.y = 0;
transform.position += vectorToUse * Time.deltaTime * 5;
}
if (Input.GetKey(KeyCode.S))
{
Vector3 vectorToUse = -camera.forward;
vectorToUse.y = 0;
transform.position += vectorToUse * Time.deltaTime * 5;
}
if (Input.GetKey(KeyCode.W))
{
Vector3 vectorToUse = camera.forward;
vectorToUse.y = 0;
transform.position += vectorToUse * Time.deltaTime * 5;
}
if (Input.GetKey(KeyCode.Space))
{
Vector3 vectorToUse = camera.up;
transform.position += vectorToUse * Time.deltaTime * 10;
}
else
{
if ( posY >= 0)
{Vector3 vectorToUse = camera.up;
transform.position -= vectorToUse * Time.deltaTime * 10;
}
else
{
Vector3 vectorToUse = camera.up;
vectorToUse.y = 0;
transform.position -= vectorToUse * Time.deltaTime * 10;
}
}
}
}
Example Image:
Please ignore the shadow as it's not working correctly just now.
TLDR; The best way to make an object jump and fall with a bounce on Keypress when moving in relation to a fixed camera position?
Are you trying to handle this in animation or in physics? Looking at the code it looks like pure controller animation, so I'd suggest that you track your jump state explicitly instead of just using the y > 0 check every update. It's a lot easier to see what's going on if you know the state of the object.
Your code makes it look like you pop up by (10 * deltaTime) when you hit space and then immediately pop down by 10 until you are below zero. Are you expecting the player to hold down space to fly, jetpack-style? Otherwise you should give an initial impulse up and then subtract from it to give a smooth fall.
Here's a very simple example. The up vector is world up (not Camera up as in your example) but if you're camera is not rolling the result would be the same.
public class DoJump : MonoBehaviour {
public float JumpSpeed = .25f;
public bool Jumping;
Vector3 jumpVec;
void Start () {
Jumping = false;
}
void Update () {
if (Jumping)
{
transform.position += jumpVec * Time.deltaTime;
jumpVec += (Vector3.down * Time.deltaTime);
//accelerate downward one unit per second per second
}
else
{
if (Input.anyKeyDown)
{
Jumping = true;
jumpVec = Vector3.up * (JumpSpeed * Time.SmoothDeltaTime);
// impulse up # jumpSpeed units per second
}
}
}
void LateUpdate()
{
if (transform.position.y < 0)
{
transform.position = new Vector3(transform.position.x, 0, transform.position.z);
Jumping = false;
}
}
}
If you're going to have uneven terrain, you should probably use physics colliders or raycast to know when to stop falling.
This is my code, hope it can help you:
public class Player : MonoBehaviour
{
public float m_gravity=10f;
void Jump()
{
if (m_ch.isGrounded) //this is the point
{
m_Gravity = 10;
if (Input.GetKeyDown(KeyCode.Space))
{
m_Gravity = -8;
}
}
else
{
m_Gravity += 10f * Time.deltaTime;
if (m_Gravity >= 10) { m_Gravity = 10; }
}
}
}

Categories