I've created an object and I've added a health bar, but when I want to shoot while using RayCast it stops the game. I don't know what can I do more or change. I don't want to create projectiles/balls to shoot.
So this is EnemyHealth assigned to Enemy object:
public class EnemyHealth : MonoBehaviour
{
public float maxHealth = 100f;
public float health;
void Start()
{
health = maxHealth;
}
public void TakeDamage(float damageAmount)
{
health -= damageAmount;
if(health <= 0)
{
Destroy(gameObject);
}
}
}
And this is code where I shoot and take dmg:
public class HitEnemy : MonoBehaviour
{
[SerializeField] Camera cam;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f));
if (Physics.Raycast(ray, out RaycastHit hit))
{
gameObject.GetComponent<EnemyHealth>().TakeDamage(10);
}
}
}
}
Component Enemy is blank, because I don't know what can I add more.
you need to check if the ray is hitting an enemy then take damage
without checking you're looking for enemy script in maybe a wall and that's why it's giving an error
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f));
if (Physics.Raycast(ray, out RaycastHit hit))
{
if (hit.collider.GetComponent<EnemyHealth>().enabled)
{
gameObject.GetComponent<EnemyHealth>().TakeDamage(10);
}
else
{
Debug.Log("No Enemy in sight, Ray is touching : " + hit.collider.name);
}
}
}
}
It looks like you're trying to get EnemyHealth that's attached to the gaeObject. The problem with that is, you're looking for EnemyHealth on the (presumably) player controller object, not the enemy object.
Let's look at a possible solution:
void Update ( )
{
if ( Input.GetMouseButtonDown ( 0 ) )
{
// Check to see if a RayCast hits an object.
if ( Physics.Raycast ( cam.ViewportPointToRay ( new Vector3 ( 0.5f, 0.5f ) ), out var hit, cam.farClipPlane ) )
{
// Check to make sure the hit object has an 'EnemyHealth' component.
if ( hit.transform.TryGetComponent<EnemyHealth> ( out var enemyHealth ) )
{
enemyHealth.TakeDamage ( 10 );
}
}
}
}
Related
I have been on here forever it feels like and nothing is fixing the issue. So I am relatively new to c# and unity and I set up my weapon and my crosshairs. I went through and set up ray cast and got a impact effect set. When I load in and try to shoot, my impact effect seems to be landing in different positions and it never lands in the same spot. I want to get it to where the effect happens on the target where the crosshairs are.
This line was added after the fact to try and fix it but didn't end up doing anything:
Ray ray = Camera.main.ViewportPointToRay(new Vector2(0.5f, 0.5f));
Here's my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class shooting : MonoBehaviour
{
public float damage = 10;
public float range = 100;
public Camera cam;
public AudioSource audioSource;
public AudioSource audio1;
public AudioClip clip;
public AudioClip reload;
public float volume = 0.5f;
public ParticleSystem muzzleflash;
public GameObject hitEffect;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shooting();
}
if (Input.GetKey(KeyCode.R))
{
Reload();
}
}
void Shooting()
{
muzzleflash.Play();
audioSource.PlayOneShot(clip, volume);
RaycastHit hit;
Ray ray = Camera.main.ViewportPointToRay(new Vector2(0.5f, 0.5f));
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, range))
{
Debug.Log("Shooting");
}
Instantiate(hitEffect, hit.point, Quaternion.LookRotation(hit.normal));
}
void Reload()
{
audio1.clip = reload;
audio1.Play();
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.LeftShift))
{
audio1.Stop();
}
}
}
You've created a ray, you need use it.
Instantiate should be in the if block.
Specify a layer to do raycast, otherwise it can hit any collider in the path.
Ray ray = Camera.main.ViewportPointToRay(new Vector2(0.5f, 0.5f));
var mask = LayerMask.GetMask("Enemy");
if (Physics.Raycast(ray, out hit, range, mask))
{
Instantiate(hitEffect, hit.point, Quaternion.LookRotation(hit.normal));
}
If the effect is still shown at a random place, add some debug code, check the red line in the scene window.
void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawLine(ray.origin, hit.point);
}
Following a tutorial, I'm trying to use a grappling gun mechanic that utilizes a spring joint and Line Renderer.
I've got the line drawing upon mouseclick, but the end of the line is not drawing where the user clicks.
It looks like this:
Can anyone kind of help me out as to why it's not working? Here's the (wonky) project in action-
https://i.imgur.com/IuMsEsQ.mp4
Grappling gun code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrapplingGun : MonoBehaviour
{
private LineRenderer lr;
private Vector3 grapplePoint; //where we grapple to
public LayerMask whatIsGrappable;
public Transform gunTip;
public Transform cam;
public Transform player;
private float maxDistance = 100f;
private SpringJoint joint;
void Awake()
{
lr = GetComponent<LineRenderer>();
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
StartGrapple();
}
else if (Input.GetMouseButtonUp(0))
{
StopGrapple();
}
}
void LateUpdate()
{
DrawRope();
}
void StartGrapple()
{
RaycastHit hit;
if (Physics.Raycast(cam.position, cam.forward, out hit, maxDistance, whatIsGrappable))
//if (Physics.Raycast(transform.position, Vector3.forward, out hit, maxDistance, whatIsGrappable))
{
grapplePoint = hit.point;
joint = player.gameObject.AddComponent<SpringJoint>();
joint.autoConfigureConnectedAnchor = false;
joint.connectedAnchor = grapplePoint;
float distanceFromPoint = Vector3.Distance(player.position, grapplePoint);
joint.maxDistance = distanceFromPoint * 0.8f;
joint.minDistance = distanceFromPoint * 0.25f;
joint.spring = 4.5f;
joint.damper = 7f;
joint.massScale = 4.5f;
lr.positionCount = 2;
}
}
void DrawRope()
{
//If not grappling, don't draw anything
if (!joint) return;
lr.SetPosition(0, gunTip.position);
lr.SetPosition(1, grapplePoint);
}
void StopGrapple()
{
lr.positionCount = 0;
Destroy(joint);
}
}
Thank you.
The underlying issue is your raycast. the second parameter is the direction of the ray, which you have as the camera direction. Currently your ray is pointing forward from the camera at all times as a result.
What you can do is use Camera.ScreenPointToRay to give a ray to cast along to give you a 3d mouse position to cast to, then use your current raycast but replace the second parameter with the direction from the player to the point hit by the raycast from the function mentioned before
Ray ray = Camera.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray, out RaycastHit hit);
if (Physics.Raycast(transform.position, (hit.point - transform.position).normalized, out hit, maxDistance, whatIsGrappable)) {
// Your code here...
}
so I have an issue about movement click on unity it's about when I click of course the player will be moving to the position I clicked but, I don't want if I clicked on the wall and another button the player will be on the last mouse I clicked, I already add some collider but the player just bypass the collider so collider doesn't have any effect
the explanation
and this the script
[Header("Tweak")]
[SerializeField] Transform target;
Vector2 targetPos;
public float speed = 5f;
// Start is called before the first frame update
void Start()
{
targetPos = transform.position;
}
// Update is called once per frame
void Update()
{
Move();
}
public void Move()
{
if (Input.GetMouseButtonDown(0))
{
targetPos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
if ((targetPos.x >= transform.position.x))
{
transform.localScale = new Vector2(.5f, .5f);
}
else
{
transform.localScale = new Vector2(-.5f, .5f);
}
target.position = targetPos;
}
if ((Vector2)transform.position != targetPos)
{
transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
}
}
You can do this using Raycast
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
if (hitInfo.collider.gameObject.tag == "Wall")
{
Debug.Log("tag");
//You can do what ever you want here.
}
}
}
I'm currently making a sandbox game and it is able to create a object through left click. But, I am struggling to destroy a specific object when it is right clicked. I've looked on previous questions here, but they don't exactly answer my question.
using UnityEngine;
using System.Collections;
public class ControlObjects : MonoBehaviour
{
Vector3 mousePosition, targetPosition;
//To Instantiate TargetObject at mouse position
public Transform targetObject;
public GameObject Prefab;
float distance = 10f;
Ray ray;
RaycastHit hit;
//public int item_num = 1;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.position = targetPosition;
//To get the current mouse position
mousePosition = Input.mousePosition;
//Convert the mousePosition according to World position
targetPosition = Camera.main.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, distance));
//Set the position of targetObject
targetObject.position = targetPosition;
//Debug.Log(mousePosition+" "+targetPosition);
//If Left Button is clicked
if (Input.GetMouseButtonDown(0))
{
//create the instance of targetObject and place it at given position.
Instantiate(targetObject, targetObject.transform.position, targetObject.transform.rotation);
}
}
}
Implement what you need, but this is the base.
using UnityEngine;
public class Test : MonoBehaviour
{
private float distance = 10;
private float offset = -4;
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse1))
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = new Vector3
{
x = offset += 1.5f,
y = 0,
z = 0
};
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetKeyDown(KeyCode.Mouse0))
{
if(Physics.Raycast(ray, out RaycastHit hit, distance))
{
Destroy(hit.transform.gameObject);
}
}
}
}
You should have a look at IPointerClickHandler. Attach this script to the objects you want to be able to click on
using UnityEngine;
using UnityEngine.EventSystems;
public class DestroyOnRightClick : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick (PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Right)
{
Debug.Log ("Right Mouse Button Clicked on: " + name);
Destroy(gameObject);
}
}
}
Note
Ensure an EventSystem exists in the Scene to allow click detection. For click detection on non-UI GameObjects, ensure a PhysicsRaycaster is attached to the Camera.
I am integrating my game to VR and now i wanted to change my controlling. In the script given bellow when the player press the mouse button the gun fires the bullet but now in VR i don't want my game to be controlled by any controller. what i want is when player moves his head and the focus point comes to the Enemy it starts shooting without pressing any button(I mean auto shoot). what should i do??
grausing System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunScript : MonoBehaviour {
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float impactForce = 30f;
public Camera fpsCam;
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()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null)
{
target.TakeDamage(damage);
}
if(hit.rigidbody != null)
{
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
GameObject ImpactEffectGO = Instantiate(impactEffect, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(ImpactEffectGO, 2f);
}
}
}
Since you already have an existing shooting mechanic, simply changing up the Update() should do what you want
void Update () {
if (Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}