raycast not responding past a certain angle - c#

I have made a game using the unity asset First Person Controller to allow player movement and for them to look around. I have put a cross hair in where a ray cast shoots through and instantiates a bullet. There are no problems with the bullet fire above a certain angle. The bullets follow the cross hair and shoot right in the center but if I look down too far then they no longer shoot where the cross hair is and instead just shoot straight out of the camera.
I think that the capsule that the first person controller makes may be the problem as I cannot find anything in my code.
LINK TO VIDEO: https://youtu.be/zf2EuL7e_i4
Bullet Listener.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletListener : MonoBehaviour {
public Camera mainCamera;
public BulletContoller bulletPrefab;
public GameObject cursor;
private Vector3 cursorPosition;
void Update () {
if (Input.GetMouseButtonDown (0)) {
cursorPosition = cursor.transform.position;
//create ray from camera to mousePosition
Ray ray = mainCamera.ScreenPointToRay (cursorPosition);
//Create bullet from the prefab
BulletContoller newBullet = Instantiate (bulletPrefab.gameObject).GetComponent<BulletContoller> ();
//Make the new bullet start at camera
newBullet.transform.position = mainCamera.transform.position;
//set bullet direction
newBullet.SetDirection (ray.direction);
//Create Bullet Sound
AudioSource audio = GetComponent<AudioSource>();
audio.Play ();
}
}
}
Bullet Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletContoller : MonoBehaviour {
Rigidbody rb;
public float bulletForce;
bool firstTime = false;
Vector3 direction;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
}
public void SetDirection (Vector3 dir) {
direction = dir;
firstTime = true;
}
void OnCollisionEnter (Collision col) {
//code for when bullet hits something
if (col.gameObject.name == "Target") {
this.gameObject.name = "Hit";
}
}
void FixedUpdate () {
if (firstTime) {
rb.AddForce (direction * bulletForce);
firstTime = false;
}
}
}

You may be right, it can be the capsule from the controller the problem, do this:
Create 2 layers named Player and Bullets.
Place the PlayerController in the layer Player.
Place the Bullet in the layer Bullets.
Go to Edit -> Project Settings -> Physics and in the Layer Collision Matrix make sure the Player layer and the Bullets layer don't collide with each other.

Related

Move a object continuously in unity 3D

I am a beginner at unity and try to make a game by watching some tutorial. After finishing my game I wanted to add some more functionality which is dropping objects continuously from up to the plane. But after it dropped on the plane it rising up to a certain level and again dropped on the plane. I don't understand what to do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class droper : MonoBehaviour
{
// Start is called before the first frame update
MeshRenderer renderer;
Rigidbody rigidbody;
Vector3 pos1;
Vector3 pos2;
Vector3 pos3;
[SerializeField]float timeToWait =2f;
[SerializeField]float speed =0.005f;
void Start()
{
renderer = GetComponent<MeshRenderer>();
rigidbody = GetComponent<Rigidbody>();
renderer.enabled= false;
rigidbody.useGravity= false;
pos1 = transform.position;
}
// Update is called once per frame
void Update()
{
if (Time.time > timeToWait)
{
renderer.enabled= true;
rigidbody.useGravity= true;
pos2 = transform.position;
Debug.Log(pos1);
pos3=new Vector3(transform.position.x,pos1.y,transform.position.z);
if (pos2.y < pos1.y)
{
transform.position=Vector3.MoveTowards(pos2,pos3,speed);
}
}
}
}
enter image description here
You can do this in 2 ways
You can use rigidbody.velocity along the axis you want to move, you may want to disable gravity depending on what you are trying to achieve
Transform.translate is also an option but it has buggy physics so you shouldn't really use it

Enemy Projectile is not flying in the right direction?

I am having trouble getting the enemy's projectile to fly from the enemy to the player's position. When I play the game, the enemy bullet projectiles fly off in one direction on the screen and not toward the player. I think the issue might be in how I am assigning direction to the projectile prefab? Any suggestions would be much appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public float speed;
public Rigidbody enemyRb;
[SerializeField] float rateOfFire;
private GameObject player;
public GameObject projectilePrefab;
float nextFireAllowed;
public bool canFire;
Transform enemyMuzzle;
void Awake()
{
enemyRb = GetComponent<Rigidbody>();
player = GameObject.Find("Player");
enemyMuzzle = transform.Find("EnemyMuzzle");
}
void Update()
{
//move enemy rigidbody toward player
Vector3 lookDirection = (player.transform.position - transform.position).normalized;
enemyRb.AddForce(lookDirection * speed);
//overallSpeed
Vector3 horizontalVelocity = enemyRb.velocity;
horizontalVelocity = new Vector3(enemyRb.velocity.x, 0, enemyRb.velocity.z);
// turns enemy to look at player
transform.LookAt(player.transform);
//launches projectile toward player
projectilePrefab.transform.Translate(lookDirection * speed * Time.deltaTime);
Instantiate(projectilePrefab, transform.position, projectilePrefab.transform.rotation);
}
public virtual void Fire()
{
canFire = false;
if (Time.time < nextFireAllowed)
return;
nextFireAllowed = Time.time + rateOfFire;
//instantiate the projectile;
Instantiate(projectilePrefab, enemyMuzzle.position, enemyMuzzle.rotation);
canFire = true;
}
}
It looks like what is actually happening is that you create a bunch of bullets but don't store a reference to them. So each bullets sits in one place while the enemy moves closer to the player ( which might give the appearance that the bullets are moving relative to the enemy. ) I also assume the enemy is moving very fast since it is not scaled by delta time but is being updated every frame.
I think projectilePrefab is just the template object you're spawning, so you probably don't want to move it directly and you certainly don't want to instantiate a new bullet every frame.
If you want to move the object you spawned the least changes ( but still problematic ) from your example code might be:
public class EnemyController : MonoBehaviour
{
// add a reference
private GameObject projectileGameObject = null;
void Update()
{
//Update position of spawned projectile rather than the template
if(projectileGameObject != null ) {
projectileGameObject.transform.Translate(lookDirection * speed * Time.deltaTime);
}
// Be sure to remove this extra instantiate
//Instantiate(projectilePrefab, transform.position, projectilePrefab.transform.rotation);
}
public virtual void Fire()
{
//instantiate the projectile
projectileGameObject = Instantiate(projectilePrefab, enemyMuzzle.position, enemyMuzzle.rotation);
}
}
Or keep multiple bullets in a list. This implementation has the bug that it will always use the current enemy to player vector as the direction rather than the direction that existed when it was fired.
What you will probably want eventually is that each projectile is has it's own class script to handle projectile logic. All the enemyController class has to do is spawn the projectile and sets it's direction and position on a separate monobehavior that lives on the Projectile objects that handles it's own updates.

Move Object Along Raycast

I have made a Raycast that goes from my camera to the point of the object clicked. However, I am trying to make an object (in this case a bullet) to fly along the path of the ray. At the moment it flies straight forwards from the camera no matter where on the object you click because of the vector 3. How would I get it to follow the Ray?
C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RaycastShot : MonoBehaviour {
public Camera camera;
private Ray ray;
private RaycastHit hit;
public GameObject bullet;
private GameObject createBullet;
private Collider collider;
void Update () {
if (Input.GetMouseButtonDown (0)) {
ray = camera.ScreenPointToRay (Input.mousePosition);
createBullet = Instantiate (bullet, camera.transform.position, bullet.transform.rotation);
createBullet.AddComponent<Rigidbody>();
createBullet.GetComponent<Rigidbody>().AddRelativeForce (new Vector3(0, 1500, 0));
createBullet.GetComponent<Rigidbody>().useGravity = false;
collider = createBullet.GetComponent<Collider> ();
Destroy (collider);
if (Physics.Raycast (ray, out hit)) {
}
}
Debug.DrawLine (ray.origin, hit.point, Color.red);
}
}
You would want to use ray.direction property instead of (0,1500,0) as the direction of the force.
The add force should occur in FixedUpdate, and should only occur if the Ray hits something. Where you have it now is probably not the best spot.
Of course, make sure the bullet gets instantiated at the camera's location first.
Ray.direction gives you the vector3 direction of the ray object. If you need the distance at which it hit, you could also use ray.distance.
Edit: I'm near my computer now, so here's a more detailed answer relating to your comments.
First off: Here's the way I set up the test Project:
I Created a prefab bullet. This is just a sphere with a rigidbody, with my "BulletController" script attached to it. The point of prefabs is to avoid all of those lines where you have to add components. For testing purposes I set the rigibody to ignore gravity and its mass to 0.1.
Next, I created the BulletController script, which will be attached to the bullet prefab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletController : MonoBehaviour {
Rigidbody rb;
public float bulletForce;
bool firstTime = false;
Vector3 direction;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
}
public void SetDirection (Vector3 dir) {
direction = dir;
firstTime = true;
}
void OnCollisionEnter () {
//code for when bullet hits something
}
void FixedUpdate () {
if (firstTime) {
rb.AddForce (direction * bulletForce);
firstTime = false;
}
}
}
This script is is charge of controlling bullets. The (later on) script that will create the bullets doesn't really care what happens to them afterwards, since its job is just to create bullets. This BulletController script is in charge of dealing with bullets once they're created.
The main parts are the SetDirection method which tells the bullet which direction to travel in. Also it adds a one-time force in its FixedUpdate method that pushes it in the direction you just set. FixedUpdate is used for physics changes like adding forces. Don't use Update to do this kind of thing. It multiplies the force by a force that you set called "bulletForce".
Finally the BulletListener Script, which is simply attached to an empty game object in the scene. This script is in charge of listening for mouse clicks and creating bullets towards them.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletListener : MonoBehaviour {
public Camera mainCamera;
public BulletController bulletPrefab;
void Update () {
if (Input.GetMouseButtonDown (0)) {
//create ray from camera to mousePosition
Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);
//Create bullet from the prefab
BulletController newBullet = Instantiate (bulletPrefab.gameObject).GetComponent<BulletController> ();
//Make the new bullet start at camera
newBullet.transform.position = mainCamera.transform.position;
//set bullet direction
newBullet.SetDirection (ray.direction);
}
}
}
In the inspector for this empty game object, I added this script, and then dragged the camera, and the bulletPrefab into the appropriate fields. Be sure to drag the prefab from the FOLDER, not from the SCENE. Since this will use the prefab, not an object in the scene.
Now click around and you'll see the bullets flying! Note that using a low force is good to test, and then increase it later.
The main things to take away from this is to split up your logic. A script should only be in charge of one thing. For example, your enemies might also fire bullets. You can now reuse your bulletController script for those bullets as well. Also, say you have different sized or shaped bullets, you can just drag the bulletcontroller script onto the different prefabs you've made for your bullets. This will not affect your listener script which will still create bullets where you click.
If you have the end point then you can move along the vector with MoveTowards:
Vector3 target = hit.point;
StartCoroutine(MoveAlong(target));
private IEnumerator MoveAlong(Vector3 target){
while(this.transform.position != target){
this.transform.position = MoveTowards(this.transform.position, target, step);
yield return null;
}
}

Fly swatter movement in Unity

I am creating a game on unity (my first 2D game) and the idea of this game is to kill a fly using swatter but the problem is in the fly movement (top to down) and the collision between the swatter and the fly.
This is my code but I don't know why the collision doesn't work
using UnityEngine;
using System.Collections;
public class SwatterController : MonoBehaviour {
public float speed = 1.5f;
private Vector3 target;
void Start () {
target = transform.position;
}
void Update () {
//Movement of swatter when I click on the screen
if (Input.GetMouseButtonDown(0)) {
target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
target.z = transform.position.z;
}
transform.position = Vector3.MoveTowards(transform.position, target, speed * 5);
}
void OnCollisionEnter2D(Collision2D other){
Debug.Log ("dead");
}
}
and I would like to know how correct my code to get right movement of the swatter( the fly swatter is placed behind the camera)
and if you have an example please post it.
Objects used : Fly( circle collider 2D) , swatter(box collider 2D)

Unity3d OnTriggerEnter2D not firing

I'm currently trying to make a Unity3d (Or 2D in this case) Platformer tech demo.
While working on the demo I ran into a bit of a snag because I want my Player object to be able to go up slopes, but if I apply gravity while the Player object is on the ground it will not be able to go up slopes, even if it can go down them. My solution was to turn off gravity while the PLayer object was touching the ground, and turn it back on when it wasn't. I did this by using the functions void OnCollisionEnter2D(Collision2D collision) to turn the gravity off, and void OnCollisionExit2D(Collision2D collision) to turn it back on.
This did not work, so I played with it a bit and thought of the idea to give the ground, and Player object "Trigger Boxes" which are unseen child Cube objects that have a Collider marked as a Trigger. So now I am using the function void OnTriggerEnter2D(Collider2D collision) to turn the gravity off, and void OnTriggerExit2D(Collider2D collision) to turn it back on. But this also does not work. Below is my code, first is the Player object's main script, and after that is the Player object's "TriggerBox" and after that will be images to show how my objects are setup in Unity.
The result: The Player class currently does not collide with the ground, and falls through it to infinity.
What I want: The player to collide with the ground, and the player's TriggerBox to collide with the ground's "TriggerBox" and turn off the Player's gravity.
Notes: I've tried giving the players, and ground RigidBody2Ds. The player collides with the ground and gets jittery, and does not trigger the gravity turn-off, and the ground falls on contact with the player when the ground has the RigidBody2D. It is unknown what triggers, as the ground falls right under the player.
using UnityEngine;
using System.Collections;
public class PlayerControls : MonoBehaviour {
CharacterController controller;
private float speed = 0.004f;
private float fallSpeed = 0.01f;
private Vector3 tempPos;
bool onGround = false;
public void setOnGround(bool b){ onGround = b; }
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
tempPos = Vector3.zero;
if(Input.GetKey(KeyCode.W)) tempPos.y -= speed;
if(Input.GetKey(KeyCode.S)) tempPos.y += speed;
if(Input.GetKey(KeyCode.A)) tempPos.x -= speed;
if(Input.GetKey(KeyCode.D)) tempPos.x += speed;
RaycastHit2D[] hits = Physics2D.RaycastAll(new Vector2(transform.position.x,transform.position.y), new Vector2(0, -1), 0.2f);
float fallDist = -fallSpeed;
if(hits.Length > 1){
Vector3 temp3Norm = new Vector3(hits[1].normal.x, hits[1].normal.y, 0);
Vector3 temp3Pos = new Vector3(tempPos.x, tempPos.y, 0);
temp3Pos = Quaternion.FromToRotation(transform.up, temp3Norm) * temp3Pos;
tempPos = new Vector2(temp3Pos.x, temp3Pos.y);
}
if(!onGround) tempPos.y = fallDist;
transform.Translate(tempPos);
}
}
Next the TriggerBox:
using UnityEngine;
using System.Collections;
public class PlayerTriggerBox : MonoBehaviour {
public PlayerControls playerControls;
// Use this for initialization
void Start () {
//playerControls = gameOGetComponent<PlayerControls>();
if(playerControls == null) Debug.Log("playerControls IS NULL IN PlayerTriggerBox!");
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter2D(Collider2D other) {
playerControls.setOnGround(true);
}
void OnTriggerExit2D(Collision2D collision){
playerControls.setOnGround(false);
}
}
-As for the images for my setup-
The player's setup:
The player's TriggerBox setup:
The ground's setup:
The ground's TriggerBox setup:
Thank you for your time reading this, and hopefully for your help.

Categories