Unity hit.rigidbody reference to concrete gameObject - unity3d

I've got Menu with 3d texts. Main Camera has got animations that I want to play after clicking on text. Every text has its own rigidbody and collider. I made this code:
#pragma strict
import UnityEngine;
var object : GameObject;
var Run : AnimationPlay;
function start(){
Run = object.GetComponent(AnimationPlay);
}
function Update() {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit;
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, hit)) {
if (hit.rigidbody != null){
Debug.Log("Start Game pushed");
Run.action = true;
}
}
}
}
for Start Game button and this one:
#pragma strict
import UnityEngine;
var object : GameObject;
var Run : AnimationPlay2;
function start(){
Run = object.GetComponent(AnimationPlay2);
}
function Update() {
if (Input.GetMouseButtonDown(0)) {
var hit: RaycastHit;
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, hit)) {
if (hit.rigidbody != null){
Debug.Log("Back pushed");
Run.action2 = true;
}
}
}
}
for Back button.
The problem is it's no matter on which rigidbody I will click, both animations are starting to play and that makes weird effects. I don't know how to make a reference to concrete gameObject's rigidbody.

I solved my problem. I replaced
hit.rigidbody != null
with
hit.rigidbody.gameObject.tag == "StartGame" //object's tag here
and now it works fine.

Related

Unity - How to jump using a NavMeshAgent and click to move logic

I am building a game where the player can be controlled using the mouse input, using a click to move logic via a navmesh agent.
In order to let the player jump, I started using a CharacterController as well which should help managing the player. My issue is that I can't figure out where to put the jump logic. All references I found are related using the character controller without the navmesh agent.
I can get rid of the CharacterController if needed, but the NavMeshAgent has to stay.
Here it is a working code which allows to walk. Can you please help me with the jumping logic?
private NavMeshAgent _agent;
private CharacterController _characterController;
private Vector3 _desVelocity;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction, out RaycastHit hitInfo))
{
_agent.destination = hitInfo.point;
}
}
var currMovementDirection = _desVelocity.normalized * currentSpeed;
if (_agent.remainingDistance > _agent.stoppingDistance)
{
_desVelocity = _agent.desiredVelocity;
_characterController.Move(currMovementDirection * Time.deltaTime);
}
}
You can achieve this using a Rigidbody instead of a CharacterController. The trick is that you need to disable the NavMeshAgent in order to jump.
Optionally, you set the destination to where you are at the time of the jump, so that the agent doesn't continue the simulation while the jump is happening.
Using collision detection, you turn the NavMeshAgent back on again once you land.
public class PlayerMovement : MonoBehaviour
{
private Camera cam;
private NavMeshAgent agent;
private Rigidbody rigidbody;
public bool grounded = true;
void Start()
{
cam = Camera.main;
agent = GetComponent<NavMeshAgent>();
rigidbody = GetComponent<Rigidbody>();
}
void Update()
{
// clicking on the nav mesh, sets the destination of the agent and off he goes
if (Input.GetMouseButtonDown(0) && (!agent.isStopped))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
agent.SetDestination(hit.point);
}
}
// when you want to jump
if (Input.GetKeyDown(KeyCode.Space) && grounded)
{
grounded = false;
if (agent.enabled)
{
// set the agents target to where you are before the jump
// this stops her before she jumps. Alternatively, you could
// cache this value, and set it again once the jump is complete
// to continue the original move
agent.SetDestination(transform.position);
// disable the agent
agent.updatePosition = false;
agent.updateRotation = false;
agent.isStopped = true;
}
// make the jump
rigidbody.isKinematic = false;
rigidbody.useGravity = true;
rigidbody.AddRelativeForce(new Vector3(0, 5f, 0), ForceMode.Impulse);
}
}
/// <summary>
/// Check for collision back to the ground, and re-enable the NavMeshAgent
/// </summary>
private void OnCollisionEnter(Collision collision)
{
if (collision.collider != null && collision.collider.tag == "Ground")
{
if (!grounded)
{
if (agent.enabled)
{
agent.updatePosition = true;
agent.updateRotation = true;
agent.isStopped = false;
}
rigidbody.isKinematic = true;
rigidbody.useGravity = false;
grounded = true;
}
}
}
}
The jump logic should be inside the Update() method since we want the height to be calculated every frame.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction, out RaycastHit hitInfo))
{
_agent.destination = hitInfo.point;
}
}
var currMovementDirection = _desVelocity.normalized * currentSpeed;
groundedPlayer = _characterController.isGrounded;
if (groundedPlayer && currMovementDirection.y < 0)
{
currMovementDirection.y = 0f;
}
// Changes the height position of the player..
if (Input.GetButtonDown("Jump") && groundedPlayer)
{
currMovementDirection.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
}
currMovementDirection.y += gravityValue * Time.deltaTime;
if (_agent.remainingDistance > _agent.stoppingDistance)
{
_desVelocity = _agent.desiredVelocity;
_characterController.Move(currMovementDirection * Time.deltaTime);
}
}
Please see the official docs here

Unity - Drag with right mouse button?

I am creating a build in Unity 2019.4.12f1 and need to drag an object with Right Mouse button.
My C# skills are very limited, so far but i try.
This scripts is my attempt to be able to rotate a gameobject by holding right mouse button down and dragging ingame.
But it is wrong.
Can anyone help me correct it?ยด
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mouseM : MonoBehaviour
{
bool dragging = false;
void Start()
{
if (Input.GetMouseButtonDown(1))
{
dragging = true;
}
}
void Update()
{
if (Input.GetMouseButtonDown(1))
{
yourOnMouseDownFunction();
dragging = true;
}
if (Input.GetMouseButtonUp(1))
{
yourOnMouseUpFunction();
dragging = false;
}
if (dragging)
{
yourOnMouseDragFunction();
}
}
}
I understood that You need to Drag Object in 3d World so Here is my Code just create new Script and attach to Object You Want to Drag it
Your Object that You need to Drag it should has a collider
using UnityEngine;
public class DragableObject : MonoBehaviour
{
private Vector3 mOffset;
private float mZCoord;
private void OnMouseDrag()
{
transform.position = GetMouseWorldPos() + mOffset;
}
private void OnMouseDown()
{
mZCoord = Camera.main.WorldToScreenPoint(gameObject.transform.position).z;
mOffset = transform.position - GetMouseWorldPos();
}
private Vector3 GetMouseWorldPos()
{
Vector3 mosePoint = Input.mousePosition;
mosePoint.z = mZCoord;
var result = Camera.main.ScreenToWorldPoint(mosePoint);
return result;
}
}
you can try it by adding it to sphere or cube and if you use custom shape you should insure that the collider is in suitable size or has a meshcollier
Demo
EDIT
using UnityEngine;
public class DragableObject : MonoBehaviour
{
private bool isMouseDragging;
private Vector3 screenPosition;
private Vector3 offset;
private GameObject target;
GameObject ReturnClickedObject(out RaycastHit hit)
{
GameObject targetObject = null;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction * 10, out hit))
{
targetObject = hit.collider.gameObject;
}
return targetObject;
}
void Update()
{
if (Input.GetMouseButtonDown(1))
{
RaycastHit hitInfo;
target = ReturnClickedObject(out hitInfo);
if (target != null)
{
isMouseDragging = true;
Debug.Log("our target position :" + target.transform.position);
//Here we Convert world position to screen position.
screenPosition = Camera.main.WorldToScreenPoint(target.transform.position);
offset = target.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPosition.z));
}
}
if (Input.GetMouseButtonUp(1))
{
isMouseDragging = false;
}
if (isMouseDragging)
{
//tracking mouse position.
Vector3 currentScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPosition.z);
//convert screen position to world position with offset changes.
Vector3 currentPosition = Camera.main.ScreenToWorldPoint(currentScreenSpace) + offset;
//It will update target gameobject's current postion.
target.transform.position = currentPosition;
}
}
}
You could try the Input.GetMouseButton method, this should return a value depending on if the button is held pressed.
This one works too, if someone needs in the future.
This is for rotate though.
Sorry, i dont know why it wont let me post as code, so i post an image.
enter image description here

How to move gun backward when near to wall in unity?

I am making a FPS game in unity. I have wrote a script for gun to move back ward when it is close to a object, And also for enabling gun scope. I have used animation for gun to move back(gunBackward) and to enable scope(Scoper) and also for gun regular position(idleGun). But now in unity when I play the game I am not able to enable scope when Ray hits a collider, The gun starts vibrating. I am only able to enable scope when I look at the sky box.
public float distance;
public GameObject origin;
public bool scop;
public Animator anim;
public GameObject CrossHair;
public bool scoped;
// Use this for initialization
void Start () {
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown ("Fire2")) {
scoped = true;
scop = false;
}
if (Input.GetButtonUp ("Fire2"))
{
scoped = false;
scop = true;
}
if (scoped == true) {
anim.Play ("Scoper");
}
if (scoped == false)
{
anim.Play("idleGun");
}
Vector3 cartPos = new Vector3 (0.0f, 0.0f, 0.0f);
RaycastHit hit;
if (Physics.Raycast (cartPos+origin.transform.position, transform.TransformDirection (Vector3.forward), out hit))
{
distance = hit.distance;
}
if (hit.transform == null) {
distance = 2.1f;
return;
}
if (distance < 2)
{
anim.Play ("gunBackward");
}
if (distance > 2)
{
anim.Play("idleGun");
}
}
}

buttons only react to clicks/touches when clicking/touching to the right of them

I'm making a 2D game in Unity3D for android. Right now I'm making buttons. And this buttons does not react clicks/touched properly. I've got same issue with mouse clicks and touches both. Every button has trigger boxcollider with a same size as an object. BUT buttons react only when I click on area, that is right from a button. I don't understand why is it so. What should I do? Here is my code:
if (Input.GetMouseButtonDown(0)) {
Vector3 i = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 1));
RaycastHit2D hit = Physics2D.Raycast (i, i);
if (hit.transform != null) {
if (hit.transform.tag == "button") {
hit.transform.gameObject.SetActive(false);
}
}
}
Also, I've instantiated an object on mouse click on "i" position to check does it convert screen position to world correctly, and it works fine.
the first parameter in Physics2D.Raycast is the origin and the second one is direction so you should make the raycast from your ray.origin in the direction of ray.direction
void Update () {
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (ray.origin, ray.direction, Mathf.Infinity);
if (hit) {
if(hit.collider.gameObject.tag=="button"){
//do something
}
}
}
}
Try to handle it by this way:
if (Input.GetMouseButtonDown(0)) {
Vector3 pos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Vector2 touchPos = new Vector2(pos.x, pos.y);
Collider2D hit = Physics2D.OverlapPoint(touchPos);
if (hit) {
Debug.Log(hit.transform.gameObject.name);
if (hit.transform.tag == "button") {
hit.transform.gameObject.SetActive(false);
}
}
}

How To Respawn A Prefab After 5 Second's?

I'm trying to spawn a prefab after I destroy the object and only when the object is destroyed.
#pragma strict
function Update () {
if (Input.GetMouseButtonDown(0)) {
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit)) {
if (hit.collider.tag == "destroyable") {
Destroy(hit.collider.gameObject);
}
}
}
}
You could put the Prefab in a variable to set on unity editor:
var objectToSpawn : GameObject;
Before the Spawn code you can use:
yield WaitForSeconds (5);
Your code would look something like this:
Javascript
#pragma strict
var objectToSpawn : GameObject;
function Update () {
if (Input.GetMouseButtonDown(0)) {
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit)) {
if (hit.collider.tag == "destroyable") {
var oldTransform = hit.collider.gameObject.transform;
Destroy(hit.collider.gameObject);
StartCoroutine(SpawnAfter5Seconds(oldTransform));
}
}
}
}
function SpawnAfter5Seconds(oldTransform:Transform)
{
yield WaitForSeconds (5);
var newObject = Instantiate (objectToSpawn , oldTransform.position, oldTransform.rotation);
}