Transform instantiated bullet towards camera center - c#

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!

Related

Sprite not Appearing in Unity 2D Game

I'm creating a 2D Top Down game for practice and I need a little bit of help. For context, it's a 2D Top Down Shooter game, where you can move and shoot enemies. The enemies have a basic radius system where if the player gets within the radius, it'll approach the player.
Now I'm making a game mechanic where the player can hide in a cardboard box, the player can press 'E' and he'll suddenly become a cardboard box, where if the player is in the cardboard box, the enemy doesn't detect him even if the player's within the radius. Yes, just like in Metal Gear. Now I've created the prefabs and everything and functionality-wise, it works perfectly. If you press 'E' the enemy cannot detect you.
Now the small problem is that the cardboard box didn't appear, so it's just the player disappearing entirely. I do not know what caused this problem.
For context, these are my scripts. Feel free to read them, or not :)
PlayerController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public GameObject bulletPrefab;
public GameObject player;
private Rigidbody2D rb2d;
private Vector2 moveDirection;
[SerializeField] private Camera cam;
[SerializeField] private GameObject gunPoint;
public bool isHiding = false;
[SerializeField] private GameObject cardboardBox;
[SerializeField] private GameObject gunSprite;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
cardboardBox.SetActive(false); // Hide the cardboard box when the game starts
gunSprite.SetActive(true); // Show the gun sprite when the game starts
}
// Update is called once per frame
void Update()
{
CheckCursor();
ProcessInputs();
// Make the camera follow the player
cam.transform.position = new Vector3(player.transform.position.x, player.transform.position.y, cam.transform.position.z);
// Check if player pressed the "E" key to toggle the cardboard box
if (Input.GetKeyDown(KeyCode.E))
{
isHiding = !isHiding; // Toggle the isHiding variable
cardboardBox.SetActive(isHiding); // Show/hide the cardboard box accordingly
// If player is hiding, stop player movement
if (isHiding)
{
moveDirection = Vector2.zero;
player.GetComponent<SpriteRenderer>().enabled = false;
cardboardBox.GetComponent<SpriteRenderer>().enabled = true;
gunSprite.SetActive(false); // Hide the gun sprite when the player is hiding
}
else
{
player.GetComponent<SpriteRenderer>().enabled = true;
cardboardBox.GetComponent<SpriteRenderer>().enabled = false;
gunSprite.SetActive(true); // Show the gun sprite when the player is not hiding
}
}
}
private void FixedUpdate()
{
if (!isHiding) // Only allow player to move if they are not hiding in the cardboard box
{
Movement();
}
}
private void CheckCursor()
{
Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
Vector3 characterPos = transform.position;
if (mousePos.x > characterPos.x)
{
this.transform.rotation = new Quaternion(0, 0, 0, 0);
}
else if (mousePos.x < characterPos.x)
{
this.transform.rotation = new Quaternion(0, 180, 0, 0);
}
}
private void Movement()
{
// TODO : Implementasi movement player
rb2d.velocity = new Vector2(moveDirection.x * moveSpeed, moveDirection.y * moveSpeed);
}
private void ProcessInputs()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
moveDirection = new Vector2(moveX, moveY);
if (Input.GetMouseButtonDown(0))
{
Shoot();
}
}
private void Shoot()
{
Vector3 mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
Vector3 gunPointPos = gunPoint.transform.position;
Vector3 direction = (mousePos - gunPointPos).normalized;
GameObject bullet = Instantiate(bulletPrefab, gunPointPos, Quaternion.identity);
bullet.GetComponent<Bullet>().Init(direction);
}
}
EnemyController script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public Transform player;
public float moveSpeed = 5f;
public float detectionRadius = 5f;
public int maxHealth = 1;
private int currentHealth;
private Rigidbody2D rb2d;
private Vector2 movement;
private void Start()
{
rb2d = this.GetComponent<Rigidbody2D>();
currentHealth = maxHealth;
}
private void Update()
{
float distanceToPlayer = Vector2.Distance(transform.position, player.position);
if (player != null && distanceToPlayer <= detectionRadius && !player.GetComponent<PlayerController>().isHiding)
{
Vector3 direction = player.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
rb2d.rotation = angle;
direction.Normalize();
movement = direction;
}
else
{
movement = Vector2.zero;
}
}
void FixedUpdate()
{
moveCharacter(movement);
}
private void moveCharacter(Vector2 direction)
{
rb2d.MovePosition((Vector2)transform.position + (direction * moveSpeed * Time.deltaTime));
}
public void DestroyEnemy()
{
Destroy(gameObject);
}
}
Bullet script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
// Start is called before the first frame update
[SerializeField] private float speed;
[SerializeField] private Vector3 direction;
public void Init(Vector3 direction)
{
this.direction = direction;
this.transform.SetParent(null);
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg);
}
// Update is called once per frame
void Update()
{
this.transform.position += transform.right * speed * Time.deltaTime;
}
// TODO : Implementasi behaviour bullet jika mengenai wall atau enemy
private void OnTriggerEnter2D(Collider2D other)
{
switch(other.gameObject.tag)
{
case "Wall":
Destroy(gameObject);
break;
case "Enemy":
Destroy(gameObject);
other.gameObject.GetComponent<EnemyController>().DestroyEnemy();
break;
}
}
}
I've tried tinkering my scripts, I've tried checking if there are any missing components in the cardboard box game object but to no avail. Although I might be wrong on the Unity part since I'm fairly certain that the script isn't the problem here, again might be wrong.
I appreciate all the help I can get, thank you for reading until here

Switching camera to follow object in unity 3d

I'm trying to switch one camera to another to follow the sphere. What's happening in my script is, at first the main camera focuses the ball and as soon as it is grabbed and thrown, the main camera is switched off or disabled and the second camera is enabled to follow the ball when it is in motion. But the second camera doesn't follow in the direction of the ball. Below is the scripts that i implemented.
Note:- I'm attaching the second camera script at run time to second camera.
PickupObject.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class pickupobject : MonoBehaviour
{
GameObject mainCamera;
//public GameObject empty;
bool carrying;
public GameObject carriedObject;
// Camera cam;
public float distances;
public float smooth;
float speed = 1000f;
private Vector3 offset;
public Camera camera;
private MovingBall script;
// Use this for initialization
void Start()
{
//cam = GameObject.Find("MainCamera").GetComponent<Camera>();
mainCamera = GameObject.FindWithTag("MainCamera");
camera = GameObject.FindWithTag("secondCamera").GetComponent<Camera>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.T) && carrying)
{
carrying = !carrying;
ThrowBall();
}
if (carrying)
{
carry(carriedObject);
// CheckDrop();
}
else
{
pickup();
}
}
private void pickup()
{
if (Input.GetKeyDown(KeyCode.E))
{
int x = Screen.width / 2;
int y = Screen.height / 2;
Ray ray = mainCamera.GetComponent<Camera>().ScreenPointToRay(new Vector3(x, y));
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
pickupable p = hit.collider.GetComponent<pickupable>();
if (p != null)
{
carrying = true;
carriedObject = p.gameObject;
camera.enabled = true;
camera.gameObject.AddComponent<CameraController>();
carriedObject.AddComponent<MovingBall>();
}
}
}
}
void carry(GameObject o)
{
o.GetComponent<Rigidbody>().isKinematic = true;
o.transform.position = mainCamera.transform.position + mainCamera.transform.forward * distances;
}
//void CheckDrop()
//{
// if (Input.GetKeyDown(KeyCode.U))
// {
// Drop();
// }
//}
//void Drop()
//{
// ThrowBall();
//}
void ThrowBall()
{
mainCamera.SetActive(false);
carriedObject.GetComponent<Rigidbody>().isKinematic = false;
carriedObject.GetComponent<Rigidbody>().AddForce(0f, 0f, speed);
}
}
CameraController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour {
// Use this for initialization
public GameObject icosphere;
private Vector3 offset;
pickupobject ball = new pickupobject();
void Start () {
ball.camera = GameObject.FindWithTag("secondCamera").GetComponent<Camera>();
//offset = transform.position - icosphere.transform.position;
//icosphere = GameObject.FindWithTag("yellowball");
// icosphere = ball.carriedObject.GetComponent<GameObject>();
offset = ball.camera.transform.position - GameObject.FindWithTag("purpleball").transform.position;
}
// Update is called once per frame
void LateUpdate () {
ball.camera.transform.position = GameObject.FindWithTag("purpleball").transform.position + offset;
// transform.position = ball.carriedObject.GetComponent<GameObject>().transform.position + offset;
}
}

Unity3D Collision in Multiplayer

I'm creating a rocket league like game.
My problem is the ball.
I wrote a scipt who sets up the ball position and rigidbody based on syncvars which the server sets each 0.01 second.
This works well.
The hosting player can touch the ball and it does move on the client aswell.
My code works.
But the problem appears when I'm trying to touch the ball with a client.
The player object glitches into the ball and physics doesn't really work.
The ball gets moved sometimes but it's stil weird movement.
I guess the problem is that the ball doesn't really get the rigidbody changes from the client.
This is my code
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Ball_Behaviour : NetworkBehaviour {
[SyncVar]
public Vector3 syncedballpos;
public Vector3 ballpos;
[SyncVar]
public Quaternion syncedballrot;
public Quaternion ballrot;
public AudioClip boom;
[SyncVar]
public Vector3 syncedballrigvel;
public Vector3 rigvel;
[SyncVar]
public Quaternion syncedballrigrot;
public Quaternion rigrot;
public GameObject ball;
public Rigidbody rig;
public AudioSource aud;
public GameObject pat;
public float offset;
// Use this for initialization
override
public float GetNetworkSendInterval()
{
return 0.015f;
}
void Start () {
aud = GetComponent<AudioSource>();
GetNetworkSendInterval();
ball = this.gameObject;
rig = GetComponent<Rigidbody>();
offset = 1;
}
// Update is called once per frame
void Update ()
{
if (isServer)
{
setball();
}
if (Vector3.Distance(rigvel, syncedballrigvel) > offset)
{
rig.velocity=Vector3.Lerp(rigvel, syncedballrigvel, 1f)*Time.deltaTime*0.05f;
}
else
{
if (Vector3.Distance(ballpos, syncedballpos) > offset)
{
this.transform.position = Vector3.Lerp(ballpos, syncedballpos, 1f) * Time.deltaTime * 0.05f;
}
/* if (Quaternion.Angle(rigrot,syncedballrigrot)>1f)
{
rig.rotation = Quaternion.Slerp(rigrot,syncedballrigrot,0.7f);
}
if (Quaternion.Angle(ballrot, syncedballrot) > 1f)
{
this.transform.rotation = Quaternion.Slerp(ballrot, syncedballrot, 0.7f);
}
*/
}
}
[ServerCallback]
void setball()
{
syncedballrigvel = rig.velocity;
syncedballrigrot = rig.rotation;
syncedballpos = this.transform.position;
syncedballrot = this.transform.rotation;
// RpcDoOnClient(syncedballpos);
}
void OnCollisionEnter(Collision col)
{
aud.Play();
}
public void scored()
{
this.GetComponent<MeshRenderer>().enabled = false;
Instantiate(pat, this.transform.position, this.transform.rotation);
aud.PlayOneShot(boom,2);
}
}

How to make enemies turn and move towards player when near? Unity3D

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
}
}
}
}

How to get a projectile to shoot towards a gameobject

Im currently working on a TurretAi. I have it so that when the enemy is within a certain range the turret targets the enemy but I'm unable to get the turret to shoot the projectiles toward the enemy. this is currently what i have this is turret class.
using UnityEngine;
using System.Collections;
public class Defence : MonoBehaviour {
public float DistanceFromCastle,CoolDown;
public GameObject enemy;
public GameObject Bullet;
public int protectionRadius,bulletSpeed;
// Use this for initialization
void Start ()
{
protectionRadius = 35;
bulletSpeed = 50;
CoolDown = 5;
}
// Update is called once per frame
void Update () {
enemy = GameObject.FindGameObjectWithTag("Enemy");
if(enemy != null)
{
DistanceFromCastle = Vector3.Distance(GameObject.FindGameObjectWithTag("Enemy").transform.position,GameObject.FindGameObjectWithTag("Defence").transform.position);
//print (DistanceFromCastle);
if(DistanceFromCastle <= protectionRadius)
{
attackEnemy();
}
}
}
void attackEnemy()
{
transform.LookAt(enemy.transform);
CoolDown -= Time.deltaTime;
if (CoolDown <= 0)
{
Debug.DrawLine(transform.position,enemy.transform.position,Color.red);
Instantiate(Bullet,Vector3.forward,Quaternion.identity);
print("attack Enemy");
CoolDown = 5;
}
}
}
I also already have a cool down var so that it only shoot every 5 second any help would be awesome.
You were fairly close, you need to change this line:
Instantiate(Bullet, Vector3.forward, Quaternion.identity);
To this:
private const int SPAWN_DISTANCE = 5;
Instantiate(Bullet, transform.position + SPAWN_DISTANCE * transform.forward, transform.rotation);
Quaternion.identity refers to:
This quaternion corresponds to "no rotation".

Categories