When I shoot my bullet on a rigid body, it just moves in the wrong direction (to the right, when it is supposed to go forward) Here is the script that handle bullet and target interactions.
I have no idea why this isn't working and help would be appreciated.
thx
using UnityEngine;
public class Gun : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float impactForce = 200f;
public ParticleSystem muzzleFlash;
private float nextTimeToFire = 0f;
public Camera fpsCam;
// Update is called once per frame
void Update()
{
if (Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}
void Shoot()
{
muzzleFlash.Play();
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Target target = hit.transform.GetComponent<Target>();
if (target != null)
{
target.TakeDamage(damage);
hit.rigidbody.AddForceAtPosition(transform.forward * impactForce, hit.point);
}
}
}
}
You're using the wrong transform to get the forward vector from.
if (target != null)
{
target.TakeDamage(damage);
hit.rigidbody.AddForceAtPosition(transform.forward * impactForce, hit.point);
}
should be:
if (target != null)
{
target.TakeDamage(damage);
hit.rigidbody.AddForceAtPosition(fpsCam.transform.forward * impactForce, hit.point);
}
Related
public class PlayerMove : MonoBehaviour
{
public float speed;
private float yVelocity;
public CharacterController player;
public float jumpHeight =10.0f;
public float gravity = 1.0f;
//public float gravityScale = 1;
private void Start()
{
player = GetComponent<CharacterController>();
}
void Update()
{
Vector3 direction= new Vector3(0, 0, 1);
Vector3 velocity= direction * speed;
if (player.isGrounded == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
yVelocity = jumpHeight;
}
}
else
{
yVelocity -= gravity;
}
velocity.y = yVelocity;
player.Move(velocity * Time.deltaTime);
}
}
I tried Rigidbody & much more script but my player doesn't jump if my player jump then my doesn't move left or right sometimes my player stocked in ground.. tell me the right way of script where I can use
For the left/right movements you can try this simple code :
using UnityEngine;
public class PlayerMove : MonoBehaviour
{
public float speed;
private float yVelocity;
public CharacterController player;
public float jumpForce = 10.0f;
public float moveForce = 5.0f;
public float gravity = 1.0f;
private void Start()
{
player = GetComponent<CharacterController>();
}
void Update()
{
Vector3 direction = new Vector3(0, 0, 1);
Vector3 velocity = direction * speed;
// Add left/right movement
if (Input.GetKey(KeyCode.LeftArrow))
{
velocity += Vector3.left * moveForce;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
velocity += Vector3.right * moveForce;
}
if (player.isGrounded)
{
if (Input.GetKeyDown(KeyCode.Space))
{
yVelocity = jumpForce;
}
}
else
{
yVelocity -= gravity;
}
velocity.y = yVelocity;
player.Move(velocity * Time.deltaTime);
}
}
You can also look at this post Moving player in Subway Surf like game using left/right swipe
In my game I want to have a floating monster that's attack throws a grenade at the player. My problem is that the grenade only spawns in 0, 0, 0. In my script I make it so that the zombies spawns in on its own location but for some reason that doesn't work. I tried making it spawn by having the spawn location equal new Vector3(100, 100, 100) but it still spawned at 0, 0, 0. I know that the co-routine runs because I put a Debug.Log. Thanks for the help!
Edit #2: I can't have a rigidbody on the script. I have edited the movement script and I have found that no mater what if a rigidbody is added then it will go to 0, 0, 0.
Edit #3: I updated the scripts
Here is my script: (Sorry if the code is bad)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZKAttack_lvl3 : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 2.0f;
public float InRadius = 10.0f;
public float AttackRange = 15.0f;
private Coroutine hasCourutineRunYet;
public GameObject grenade;
public GameObject FloatingMonster;
private Vector3 FloatingMon;
private Animator anim;
private Rigidbody rigid;
private void Start()
{
anim = GetComponent<Animator>();
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
rigid = GetComponent<Rigidbody>();
}
void Update()
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player);
float dstSqr = (Player.position - transform.position).sqrMagnitude;
bool inRadius = (dstSqr <= InRadius * InRadius);
bool inAttackRange = (dstSqr <= AttackRange * AttackRange);
anim.SetBool("AttackingPlayer", inAttackRange);
if (inRadius)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
}
rigid.AddForce(1, 10, 1);
if (inAttackRange)
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeAttack());
}
}
}
IEnumerator GrenadeAttack()
{
FloatingMon = FloatingMonster.transform.position;
GameObject bulletObject = Instantiate(grenade, FloatingMonster.transform.position, Quaternion.identity);
yield return new WaitForSeconds(2.0f);
}
}
Edit: This is the code for the movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrenadeMovement : MonoBehaviour
{
public float speed = 10f;
public float lifeDuration = 4.0f;
private float lifeTimer;
private Coroutine hasCourutineRunYet;
private Transform Player;
public SphereCollider sphereCollider;
// Use this for initialization
void Start()
{
lifeTimer = lifeDuration;
sphereCollider.enabled = false;
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
}
// Update is called once per frame
void Update()
{
lifeTimer -= Time.deltaTime;
if (lifeTimer >= 3f)
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player);
transform.position += transform.forward * speed * Time.deltaTime;
}
if (lifeTimer >= 0f)
{
transform.position = speed * transform.up * Time.deltaTime;
transform.position = speed * transform.forward * Time.deltaTime;
}
if (lifeTimer <= 0f)
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
private void OnTriggerEnter(Collider coll)
{
if (coll.gameObject.tag == "Player")
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
IEnumerator GrenadeExplosion()
{
sphereCollider.enabled = true;
yield return new WaitForSeconds(1.0f);
Destroy(gameObject);
}
}
With the help of #ken I figured out that I couldn't use a rigidbody so I changed the insantiation to this: GameObject bulletObject = Instantiate(grenade, FloatingMonster.transform.position, Quaternion.identity);. I then changed the movement script for it to:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrenadeMovement : MonoBehaviour
{
public float speed = 10f;
public float lifeDuration = 4.0f;
private float lifeTimer;
private Coroutine hasCourutineRunYet;
private Transform Player;
public SphereCollider sphereCollider;
public Vector3 velocity;
// Use this for initialization
void Start()
{
lifeTimer = lifeDuration;
sphereCollider.enabled = false;
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
}
// Update is called once per frame
void Update()
{
lifeTimer -= Time.deltaTime;
if (lifeTimer >= 2f)
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player);
transform.position += transform.forward * 5 * Time.deltaTime;
}
if (lifeTimer >= 0f && lifeTimer <= 2f)
{
transform.position = 9.18f * transform.up * Time.deltaTime;
transform.position = 9.18f * transform.forward * Time.deltaTime;
}
if (lifeTimer <= 0f)
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
private void OnTriggerEnter(Collider coll)
{
if (coll.gameObject.tag == "Player" || coll.gameObject.tag == "Terrain")
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
IEnumerator GrenadeExplosion()
{
sphereCollider.enabled = true;
yield return new WaitForSeconds(1.0f);
Destroy(gameObject);
}
}
Thank you for all your help, I have been trying to fix this all week.
You could set its position in the Instantiate line. Instantiate has several arguments. You can set its position in Instantiate, as well as its rotation and parent.
Set it to this:
IEnumerator GrenadeAttack()
{
GameObject bulletObject = Instantiate(grenade, FloatingMonster.transform.position, Quaternion.identity);
yield return new WaitForSeconds(2.0f);
}
My gun code is linked to the gun itself, however even when I'm not holding the gun (aka it's not picked up yet) the gun still shoots and fires at where I'm looking, I will give the code and I'm thinking of something like 'if is child then shoot'.
Here is the code in question, if you need the full code I'd be happy to oblige.
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float Impact = 40f;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
private float nextTimeToFire = 0f;
// Update is called once per frame
void Update()
{
if (Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}
void Shoot()
{
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float Impact = 40f;
public Camera fpsCam;
public bool pickedUp = false;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
private float nextTimeToFire = 0f;
// Update is called once per frame
void Update()
{
if (Input.GetButton("Fire1") && Time.time >= nextTimeToFire && pickedUp)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}
When the gun is picked up, set the pickedUp boolean to true and false when it is dropped.
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float Impact = 40f;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
private float nextTimeToFire = 0f;
// Update is called once per frame
void Update()
{
if (Input.GetButton("Fire1") && Time.time >= nextTimeToFire && parent != null)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}
I have made a very simple gun script, currently the bullet transform in the same direction as the GameObject i have set as the bullet spawn position. but i want the bullet to transform towards the center of the camera, i have a couple of different ideas. The 1st one is shooting a raycast when the raycast hit something transform the bullet form bulletpos to raycasthit position. But i dont quite know how to do this, can anyone help me?
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gun : MonoBehaviour {
public Transform bulletCapTransform;
public GameObject bulletCap;
public float ammo;
public float magAmmo;
public GameObject shootEffect;
public Transform bulletTransform;
public GameObject bullet;
public float bulletForce;
public GameObject crossHair;
public float fireRate = 0.3333f;
private float timeStamp;
Animator anim;
// Use this for initialization
void Start ()
{
anim = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update ()
{
Shoot();
Aim();
}
public void OnGUI()
{
GUI.Box(new Rect(10, 10, 50, 25), magAmmo + " / " + ammo);
}
public void Shoot()
{
if(Time.time >= timeStamp && Input.GetButton("Fire1") && magAmmo > 0)
{
GameObject bulletCapInstance;
bulletCapInstance = Instantiate(bulletCap, bulletCapTransform.transform.position, bulletCapTransform.rotation) as GameObject;
bulletCapInstance.GetComponent<Rigidbody>().AddForce(bulletCapTransform.right *10000);
GameObject bulletInstance;
bulletInstance = Instantiate(bullet, bulletTransform) as GameObject;
bulletInstance.GetComponent<Rigidbody>().AddForce(bulletTransform.forward * bulletForce);
Instantiate(shootEffect, bulletTransform);
timeStamp = Time.time + fireRate;
magAmmo = magAmmo -1;
}
if(Input.GetKeyDown(KeyCode.R))
{
//This is just for testing
magAmmo = magAmmo + 10;
}
}
void Aim()
{
if(Input.GetButton("Fire2"))
{
anim.SetBool("Aiming", true);
crossHair.SetActive(false);
}
else
{
anim.SetBool("Aiming", false);
crossHair.SetActive(true);
}
}
}
So i think you want to fire a projectile from a "gun" object towards whatever is at the centre of your screen (regardless of central objects distance)
This script is working for me and shoots dead into the centre of the view.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gun : MonoBehaviour
{
public Transform bulletCapTransform;
public GameObject bulletCap;
public float ammo;
public float magAmmo;
public GameObject shootEffect;
public Transform bulletTransform;
public GameObject bullet;
public float bulletForce;
public GameObject crossHair;
public float fireRate = 0.3333f;
private float timeStamp;
Animator anim;
// Use this for initialization
void Start()
{
anim = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
Shoot();
Aim();
}
public void OnGUI()
{
GUI.Box(new Rect(10, 10, 50, 25), magAmmo + " / " + ammo);
}
public void Shoot()
{
if (Time.time >= timeStamp && Input.GetButton("Fire1") && magAmmo > 0)
{
Debug.Log("shoot");
GameObject bulletCapInstance;
bulletCapInstance = Instantiate(bulletCap, bulletCapTransform.transform.position, bulletCapTransform.rotation) as GameObject;
bulletCapInstance.GetComponent<Rigidbody>().AddForce(bulletCapTransform.right * 10000);
//This will send a raycast straight forward from your camera centre.
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
RaycastHit hit;
//check for a hit
if (Physics.Raycast(ray, out hit))
{
// take the point of collision (make sure all objects have a collider)
Vector3 colisionPoint = hit.point;
//Create a vector for the path of the bullet from the 'gun' to the target
Vector3 bulletVector = colisionPoint - bullet.transform.position;
GameObject bulletInstance = Instantiate(bullet, bulletTransform) as GameObject;
//See it on it's way
bulletInstance.GetComponent<Rigidbody>().AddForce(bulletVector * bulletForce);
}
Instantiate(shootEffect, bulletTransform);
timeStamp = Time.time + fireRate;
magAmmo = magAmmo - 1;
}
if (Input.GetKeyDown(KeyCode.R))
{
//This is just for testing
magAmmo = magAmmo + 10;
}
}
void Aim()
{
if (Input.GetButton("Fire2"))
{
anim.SetBool("Aiming", true);
crossHair.SetActive(false);
}
else
{
anim.SetBool("Aiming", false);
crossHair.SetActive(true);
}
}
}
The crucial point to remember is this:
Camera.main.ViewportPointToRay(0.5, 0.5, 0);
Will shoot a raycast dead ahead from the centre of your screen.
It's worth really getting to know raycasting and it's ins and outs. it seems daunting at first but its so useful once you've got it down and it's pretty intuitive. There are a lot of good youtube tutorials.
Hope your game turns out good!
I am trying to make my enemy object turn and start moving towards my player object when the player comes within a certain vicinity.
For the turning I have been testing the transform.LookAt() function although it isn't returning the desired results as when the player is too close to the enemy object the enemy starts to tilt backwards and I only want my enemy to be able to rotate along the y axis, thanks in advance.
using UnityEngine;
using System.Collections;
public class EnemyController : MonoBehaviour {
public Transform visionPoint;
private PlayerController player;
public Transform Player;
public float visionAngle = 30f;
public float visionDistance = 10f;
public float moveSpeed = 2f;
public float chaseDistance = 3f;
private Vector3? lastKnownPlayerPosition;
// Use this for initialization
void Start () {
player = GameObject.FindObjectOfType<PlayerController> ();
}
// Update is called once per frame
void Update () {
// Not giving the desired results
transform.LookAt(Player);
}
void FixedUpdate () {
}
void Look () {
Vector3 deltaToPlayer = player.transform.position - visionPoint.position;
Vector3 directionToPlayer = deltaToPlayer.normalized;
float dot = Vector3.Dot (transform.forward, directionToPlayer);
if (dot < 0) {
return;
}
float distanceToPlayer = directionToPlayer.magnitude;
if (distanceToPlayer > visionDistance)
{
return;
}
float angle = Vector3.Angle (transform.forward, directionToPlayer);
if(angle > visionAngle)
{
return;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, directionToPlayer, out hit, visionDistance))
{
if (hit.collider.gameObject == player.gameObject)
{
lastKnownPlayerPosition = player.transform.position;
}
}
}
}
change the look at target:
void Update () {
Vector3 lookAt = Player.position;
lookAt.y = transform.position.y;
transform.LookAt(lookAt);
}
this way the look at target will be on the same height as your object.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyMovement : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 4;
int MaxDist = 10;
int MinDist = 5;
void Update()
{
transform.LookAt(Player);
if (Vector3.Distance(transform.position, Player.position) >= MinDist)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, Player.position) <= MaxDist)
{
// Put what do you want to happen here
}
}
}
}