I'm working on a gun turret. I've got everything working except having the projectile shoot out of the turret gun barrel. Currently, the only barrel used is
void Start(){
firingPointRight = GameObject.FindGameObjectWithTag ("FiringPointRight").transform;
firingPointLeft = GameObject.FindGameObjectWithTag ("FiringPointLeft").transform;
}
void Update() {
if(Input.GetMouseButton(0)){
count++;
if (count >= maxCount)
{
count = 0;
//Debug.Log ("FIRE");
firingPointRight = GameObject.FindGameObjectWithTag ("FiringPointRight").transform;
firingPointLeft = GameObject.FindGameObjectWithTag ("FiringPointLeft").transform;
// Create cannon muzzle fire effect.
GameObject e1 = Instantiate (cannonMuzzleFire) as GameObject;
e1.transform.position = firingPointRight.transform.position;
e1.transform.rotation = firingPointRight.transform.rotation;
Destroy (e1, 0.03f);
GameObject e2 = Instantiate (cannonMuzzleFire) as GameObject;
e2.transform.position = firingPointLeft.transform.position;
e2.transform.rotation = firingPointLeft.transform.rotation;
Destroy (e2, 0.03f);
//-------------------------------------------
//Left cannon. Fire projectile from cannon.
//Debug.Log ("Firing Left");
Rigidbody InstantiateedProjectile = Instantiate(cannonAmmo, firingPointLeft.transform.position, firingPointLeft.transform.rotation) as Rigidbody;
if (InstantiateedProjectile != null)
{
print ("Firing projectile");
InstantiateedProjectile.transform.Translate(Vector3.forward * cannonAmmoSpeed * Time.deltaTime);
}
}
}
Does the projectile have a script of its own? It doesn't look like you're setting any velocity to the instantiated projectile.
Translate() doesn't really perform much in the way of movement, other than immediately setting the new position. If the projectile has a Rigidbody component attached, then you can just directly set the velocity of the rigidbody.
Like so:
InstantiateedProjectile.velocity = Vector3.forward * cannonAmmoSpeed;
Time.deltaTime wouldn't be used here, since it only needs to be included in calculations performed every frame.
As a side note, you might wish to consider reusing your flare effect instead of spawning a new one every shot. You can make the effect invisible and reset it between shots instead, which would give better performance.
Related
I am a starter in Unity and developing a soccer game. I have a problem ,my IF statements conflict each other. Let me explain it in detail.
In order for a ball to stick to player, I have used IF operator, so whenever the distance between the player and the ball is less than < 0.5 , the ball sticks to player and move together with it. Now when I try to set up shooting the ball (I try with "addforce") it doesnt let me, cause the ball is still attached to player and distance is <0.5.
This one is the balls script.
public bool sticktoplayer;
public transform player;
//gameobject Player is attached
float distancetoplayer;
Rigidbody rb;
//balls rigidbody
void Awake ()
{
rb = getComponent<Rigidbody>();
}
void Update()
{
If (!sticktoplayer)
{
float distancetoplayer = Vector3.Distance (player.position, transform.position);
if(distancetoplayer < 0.5f)
{
sticktoplayer = true;
}
}
else
{
transform.position = player.position;
}
if(Input.GetKeyDown(KeyCode.Space))
{
rb.addforce(20, 0, 0, ForceMode.Impulse);
sticktoplayer = false;
}
When the player is not controlling the ball the force is succesfully applied to the ball, but when the ball is attached (distancetoplayer<0.5) then the other IF statements blocks it from shooting.
Maybe there are some work arounds ? Thanks.
I tried to make another if statement.
why dont you try sticking the ball to the player by collision? instead of checking the distance, create a collider with the radius or scale you desire and whenever the ball is inside the collider (when it triggers with the collider) stick it to the player. Because you will not be able to let the ball go since the ball will always be less then 0.5f away from the player once it sticks
have you tried it this way?
if(Input.GetKeyDown(KeyCode.Space))
{
sticktoplayer = false;
rb.addforce(20, 0, 0, ForceMode.Impulse);
}
I'm trying to design a spitball/poison type projectile that will travel until it reaches the point clicked on screen and then destroys itself.
The problem is that contrary to what almost everyone says, Vector3.Movetowards is not moving the ball at a constant speed. If the target location is close to the launcher it moves slowly, if it is further away it moves much faster.
public float speed = 5f;
public Vector3 target = new Vector3();
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, target,speed * Time.deltaTime);
}
Adding the launcher script
private void Shooting()
{
if (Input.GetMouseButton(0))
{
if (Time.time >= shotTime)
{
GameObject poison = Instantiate(Projectile, shotPoint.position, transform.rotation);
Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
target.z = 10f;
poison.GetComponent<PoisonBall>().target = target;
shotTime = Time.time + timeBetweenShots;
}
}
}
Is the balls start position also at z=10f? Otherwise the difference in the speed most probably is a perspective issue in a 2D game and results in your bullet traveling in the Z direction but from your camera perspective you don't see that.
=> The closer you will be to the target the more movement will only happening on the Z axis, the further away the more movement is happening on X and Y.
Make sure to also do
var spawn = shotPoint.position;
spawn.z = 10f;
GameObject poison = Instantiate(Projectile, spawn, transform.rotation);
Or alternatively keep target.z = 0 (just remove the line target.z = 10f as per default the ScreenToWorld uses the Z component of given vector as depth and you are passing in a 2D vector with 0 depth anyway) and instead use Vector2.MoveTowards which will ignore ant depth on Z.
I have a problem with camera in Unity. I want to follow to the ball. I want to make auto respawn for the ball and camera. But the code works but camera doesn't follow to the ball.
This is code for auto respawn:
public class start : MonoBehaviour
{
public GameObject Camera;
public GameObject Ball;
void Start()
{
GameObject ball = GameObject.Instantiate(Ball);
Ball.name = "Ball";
ball.transform.position = transform.position + Vector3.up * 0.5f;
Instantiate(Camera);
Camera.name = "Camera";
Camera.transform.position = transform.position + new Vector3(0.25f, 1.75f, 6.5f);
}
The code for camera controller:
public Transform Ball;
void Update()
{
Rigidbody rigidbody = Ball.GetComponent<Rigidbody>();
float ballVelocity = rigidbody.velocity.sqrMagnitude;
UnityEngine.Vector3 vector = new UnityEngine.Vector3(0, 4, 7);
vector *= (1+ ballVelocity / 30);
UnityEngine.Vector3 nowaPozycjaKamery = Ball.position + vector;
transform.position = UnityEngine.Vector3.Lerp(transform.position, nowaPozycjaKamery, Time.deltaTime*5);
transform.LookAt(Ball);
}
Camera worked well before auto respawn. Code work that on start camera follow to good position, but is freezed when the ball change the position.
I wish you provided more information on this question. Like is there any NullReferenceException or other exceptions. But I'll try to answer your issue anyways. I think the problem is that the camera script doesn't have the reference to the new ball that's being spawned (this is in the case of destroying the old ball and Instantiating a new one with Destroy(gameObject)).
What I suggest is to add a Method in the camera script that will be in charge of injecting the new ball into the script. And then you call this method with the new spawned ball in the script responsible for spawning. Or a more straightforward but not efficient way is to check if the ball property is null and then you make a call to GameObject.Find("Name of The ball object") and you give the name of the ball object.
My game is a topdown zombie shooter and whenever the zombies get to the player they bunch up underneath them, to the point where the player can just walk over the zombies. I noticed that when I check isKinematic on the Rigidbody the zombies cant push the player up to go underneath him, so they just run into him(which is what I want). Despite this I am then unable to move. How can i fix this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoving1 : MonoBehaviour {
public float moveSpeed;
private Rigidbody myRigidbody;
private Vector3 moveInput;
private Vector3 moveVelocity;
private Camera mainCamera;
public GunController theGun;
void Start () {
myRigidbody = GetComponent <Rigidbody>();
mainCamera = FindObjectOfType<Camera>();
}
// Update is called once per frame
void Update () {
moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput * moveSpeed;
Ray cameraRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
float rayLength;
if(groundPlane.Raycast(cameraRay,out rayLength))
{
Vector3 pointToLook = cameraRay.GetPoint(rayLength);
transform.LookAt(new Vector3(pointToLook.x,transform.position.y,pointToLook.z));
}
if (Input.GetMouseButtonDown(0))
theGun.isFiring = true;
if (Input.GetMouseButtonUp(0))
theGun.isFiring = false;
}
void FixedUpdate(){
myRigidbody.velocity = moveVelocity;
}
}
With isKinematic == true You can't change object position through rigidbody, You can only change transform.position.
I think it could be better, if You set isKinematic to false and add stopping distance to enemies, so they can't get too close to player.
Being that your player can no longer be effected by the physics engine, you'd have to manipulate the object's transform manually. Your script isn't ideally setup for it currently, but if I was to hack it into it and try to make it work it would look something like this:
(you can change it from fixedUpdate to update if you're no longer utilizing the physics engine)
void update(){
float x = Input.GetAxisRaw("Horizontal")* Time.Deltatime;
float z = Input.GetAxisRaw("Vertical") * Time.Deltatime;
transform.position = new Vector3(transform.position.x+x,0,transform.position.z+z);
Another way of doing this is to lock the position of Y for the player (assuming Y is the positive "up" direction). isKinimatic is best when you want to move the player or objects around yourself.
I would say upping the mass is better in this case, and you can keep isKinematic unchecked in this case then too. Also apply the lock for Y movement (again if it is the "up" direction from the plane)
Let me know what your solution is regardless, I've had some issues in the past as well with these types of events happening
I am having my player constantly drop downwards on the screen and when the player interact with other gameobjects, I want to destroy those gameobjects and want the player to carry on dropping.
But the moment the player hits the other gameobject, the gameobject does gets destroyed but the player stops dropping. Please help advice what I am doing wrong.
//Script attached to player:
//x-axis movement speed
public float playerMoveSpeed = 0.2f;
//how much force to act against the gravity
public float upForce = 9.0f;
//horizontal control
private float move;
// Update is called once per frame
void Update()
{
//player left right x-axis movement control
move = Input.GetAxis("Horizontal") * playerMoveSpeed;
transform.Translate(move, 0, 0);
}
void FixedUpdate()
{
//to fight against the gravity pull, slow it down
rigidbody.AddForce(Vector3.up * upForce);
}
//Script attached to gameObject to be destroyed on contact with player
void OnCollisionEnter(Collision col)
{
//as long as collide with player, kill object
if (col.gameObject.tag == "Player")
{
Destroy(gameObject);
}
}
First one should solve your problem, the second one might make your life easier :)
1.) Mark the objects as "Triggers" so that no real collision happens. That way your player should just fall through and keep its speed. You also need to use OnTriggerEnter instead of OnCollisionEnter
2.) If you dont really need "forces" but just want to move the player constantly you could just turn off gravity and set rigidbody.velocity manually like(i am assuming 2d here):
void FixedUpdate()
{
horizontalVelocity = Input.GetAxis("Horizontal") * playerMoveSpeed;
rigidbody.velocity = new Vector3(horizontalVelocity, verticalVelocity, 0.0f);
}
Just play around with values for verticalVelocity and horizontalVelocity untill it feels right.
Also note that if you move something in Update() you should probably multiply the translation with Time.deltaTime or your player will move faster on higher fps. FixedUpdate is called in fixed time intervalls so you dont need it there(thats why its called Fixed Update).