Detect UI touch events in uniy3d............? - touch

Presently working on mobile 3D endless runner game.when press UI button my player running animation.when touch on mobile scree my player attacking animation. But here my problem is when pressed UI button both running and attack animation is played.
can any one suggest how to solve this problem
using System.Collections;
using UnityEngine.EventSystems;
public class TestAgain : MonoBehaviour
{
float lastTouchForDouble, lastTouchForMulti, presentTouchTime = 0.3f,multiTouchTime = 0.2f;
bool isTouch;
public GameObject ant;
public float zoomValue;
float deltaMagnitudeDiff;
Ray ray;
RaycastHit hit;
public float scaleFactor;
public float minScale = 0.05f;
public float maxScale = 1f;
void Update ()//!EventSystem.current.IsPointerOverGameObject(pointerId)
{
if (Input.touchCount > 0) {
foreach (Touch touch in Input.touches) {
if (EventSystem.current.IsPointerOverGameObject(touch.fingerId)){
return;
}
int pointerId = touch.fingerId;
if (touch.phase == TouchPhase.Ended) {
if (Input.touchCount == 1 && Input.touchCount != 2) {
if (!isTouch) {
isTouch = true;
ray = Camera.main.ScreenPointToRay (touch.position);
if (Physics.Raycast (ray, out hit)) {
if (hit.collider.name.Contains ("Player")) {
// Player attack animation
}
}
}
public void OnButtonClick()
{
//Play run animation
}

Related

Efficient way to detect touch except on the area of joystick

I'm using this joystick and Mirror for networking
https://github.com/herbou/Unity_EasyJoystick
And I have this script to fire a bullet on the user touch
public class ShootBullet : NetworkBehaviour
{
[SerializeField]
private GameObject bulletPrefab;
private GameObject bullet;
// Set via the Inspector in Units/second
[SerializeField] private float _moveSpeed = 2f;
[SerializeField] private Camera _camera;
Vector3 touch_Pos = new Vector3(0, 0, 0);
private void Awake()
{
if (!_camera) _camera = Camera.main;
}
void Update()
{
if (Input.touchCount > 0 && this.isLocalPlayer)
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
var touch = Input.GetTouch(0);
touch_Pos = _camera.ScreenToWorldPoint(touch.position);
this.CmdShoot();
}
}
if (bullet != null)
{
bullet.transform.position = Vector3.MoveTowards(bullet.transform.position, touch_Pos, _moveSpeed * Time.deltaTime);
}
}
[Command]
void CmdShoot()
{
bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
NetworkServer.Spawn(bullet);
}
}
My problem right now is it's firing a bullet when I touch the joystick area. What is the efficient way to exclude input.touch on the joystick area
You can raycast touch position and check the result.
var mousePos = Input.mousePosition;
var mouseToRay = _camera.ScreenPointToRay(mousePos);
RaycastHit hit;
if (Physics.Raycast(mouseToRay, out hit))
{
var gameObject = hit.collider.gameObject;
//Here You can check the name of your object or the layer or tag
var isMouseUnderJoyStick = gameObject.CompareTag("Your_UI_Tag");
}
And you have to add collider component to your JoyStick

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

How to spawn multiple prefab, with individual physics

I Did apply some of the responses , most likely in the wrong way.. this is still not working with this RAYCAST. What am I doing wrong here?
Want to spawn a prefab, which is a a ball, this ball is flying forward on flick finger on the screen.
What I want is to spawn OnClick FEW/Multiple of this prefab.
, prefab is spawning on Raycast Hit, BUT.. when I am flicking the object EVERY prefab in the scene is moving in the same way.
If I flick first one in to the Left, it goes there, but If now I flick second one to right, BOTH go to the RIGHT, but I would like them to work independent. Maybe this is easy fix to this but I can't find answer. (I'm planning to have up to 30/50 of this prefabs, so attaching separate scripts would be bit time consuming)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallScript1 : MonoBehaviour
{
Vector2 startPos, endPos, direction;
float touchTimeStart, touchTimeFinish;
public float timeInterval = 5f;
public float throwForceInXandY = 1f;
public float throwForceinZ = 40f;
public static bool SpawnButtonAppear = true;
public static bool thrown = false;
public static bool moving = false;
public static bool fly = false;
public bool Pressed = false;
Rigidbody rb;
public GameObject player;
public Vector3 originalPos;
public GameObject playerPrefab;
string touched;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.isKinematic = true;
}
private void OnMouseDown()
{
PlayerTest.clicked = true;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit _hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out _hit))
{
touched = _hit.collider.tag;
if (touched == "Player")
{
Invoke("spawned", 0.5f);
}
}
}
if (touched == "Player")
{
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
touchTimeStart = Time.time;
startPos = Input.GetTouch(0).position;
}
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
{
fly = false;
touchTimeFinish = Time.time;
endPos = Input.GetTouch(0).position;
direction = startPos - endPos;
rb.isKinematic = false;
rb.AddForce(-direction.x * throwForceInXandY, -direction.y * throwForceInXandY, throwForceinZ * timeInterval);
BackWall.canSpawnNow = 1;
}
}
}
public void spawned()
{
GameObject spawnedprefab = Instantiate(playerPrefab, new Vector3(originalPos.y, originalPos.x, originalPos.z), Quaternion.identity);
Destroy(spawnedprefab, 5f);
}
The thrown variable is not declared inside your class, so when you set it to true you are setting it true for all the instances of the class.
Declare the bool thrown; inside the EnemySpawn class, so that OnMouseDown, only the corresponding intance's thrown variable is set to true.

Trying to create a nice character controller?

I'm kind of new in the 2D environment of Unity.
I'm trying to create a platformer. For now, I have a simple map and my player.
My simple map and my player
My player have one script attached :
public class Player : MonoBehaviour
{
public float speed;
public float jump;
public GameObject raycastPoint; // Positioned at 0.01 pixel below the player
private SpriteRenderer spriteRenderer;
private Rigidbody2D body; // Gravity Scale of the Rigidbody2D = 50
private Animator animator;
private void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
body = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
}
private void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
if (horizontal == 1 && spriteRenderer.flipX)
{
spriteRenderer.flipX = false;
}
else if (horizontal == -1 && !spriteRenderer.flipX)
{
spriteRenderer.flipX = true;
}
body.velocity = new Vector2(horizontal * speed, body.velocity.y);
animator.SetFloat("Speed", Mathf.Abs(horizontal));
float vertical = Input.GetAxisRaw("Vertical");
if (vertical == 1)
{
RaycastHit2D hit = Physics2D.Raycast(raycastPoint.transform.position, Vector2.down, 0.01f);
if (hit.collider != null)
{
body.AddForce(new Vector2(0f, jump));
}
}
}
}
For now I have achieved the right and left movements.
For the jump, I have a child gameobject just under the player and I'm firing a raycast to the bottom so I can know if my player is grounded or not.
I have two problems.
PROBLEM NUMBER ONE.
Sometimes I feel like my "AddForce" line is executed multiple times my player is jumping really high
Problem number one image
PROBLEM NUMBER TWO.
When I'm jumping to the left or right wall, if I keep pressing the left or right key my player is not falling anymore and stay against the wall.
Problem number two image
I tried to put my code into the FixedUpdate method (I know it's better) but I had the same results.
And I tried to set the Collision Detection on Continuous but I had the same results.
Try this code for your first problem :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(BoxCollider2D))]
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Animator))]
public class Player_Controller : MonoBehaviour {
private Rigidbody2D body;
private bool canJump, facingRight;
private Animator anim;
[SerializeField]
private float moveSpeed, jumpForce;
void Start ()
{
SetStartValues();
}
void FixedUpdate ()
{
float horizontal = Input.GetAxis("Horizontal");
animator.SetFloat("Speed", Mathf.Abs(horizontal));
Flip(horizontal);
Move(horizontal);
Jump();
}
private void SetStartValues()
{
body = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
canJump = true;
facingRight = true;
}
private void Jump()
{
if (Input.GetKeyDown(KeyCode.Space) && canJump)
{
body.AddForce(new Vector2(0, jumpForce));
canJump = false;
}
}
private void Move(float x)
{
body.velocity = new Vector2(x * moveSpeed * Time.deltaTime, body.velocity.y);
}
private void Flip(float x)
{
if (x > 0 && !facingRight|| x < 0 && facingRight)
{
facingRight = !facingRight;
transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y) ;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
canJump = true;
}
}
}
And don't forget to put the "Ground" tag on your ground object.

Touch Controls unity 2D

I have script called PlayerCharacter to control a player on the Unity 2D Platform. It's perfect, working as usual.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof (Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))]
public class PlayerCharacter : MonoBehaviour
{
public float speed = 1.0f;
public string axisName = "Horizontal";
private Animator anim;
public string jumpButton = "Fire1";
public float jumpPower = 10.0f;
public float minJumpDelay = 0.5f;
public Transform[] groundChecks;
private float jumpTime = 0.0f;
private Transform currentPlatform = null;
private Vector3 lastPlatformPosition = Vector3.zero;
private Vector3 currentPlatformDelta = Vector3.zero;
// Use this for initialization
void Start ()
{
anim = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update ()
{
//Left and right movement
anim.SetFloat("Speed", Mathf.Abs(Input.GetAxis(axisName)));
if(Input.GetAxis(axisName) < 0)
{
Vector3 newScale = transform.localScale;
newScale.x = -1.0f;
transform.localScale = newScale;
Debug.Log("Move to left");
}
else if(Input.GetAxis(axisName) > 0)
{
Vector3 newScale = transform.localScale;
newScale.x = 1.0f;
transform.localScale = newScale;
Debug.Log ("Move to Right");
}
transform.position += transform.right*Input.GetAxis(axisName)*speed*Time.deltaTime;
//Jump logic
bool grounded = false;
foreach(Transform groundCheck in groundChecks)
{
grounded |= Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
}
anim.SetBool("Grounded", grounded);
if(jumpTime > 0)
{
jumpTime -= Time.deltaTime;
}
if(Input.GetButton("jumpButton") && anim.GetBool("Grounded") )
{
anim.SetBool("Jump",true);
rigidbody2D.AddForce(transform.up*jumpPower);
jumpTime = minJumpDelay;
}
if(anim.GetBool("Grounded") && jumpTime <= 0)
{
anim.SetBool("Jump",false);
}
//Moving platform logic
//Check what platform we are on
List<Transform> platforms = new List<Transform>();
bool onSamePlatform = false;
foreach(Transform groundCheck in groundChecks)
{
RaycastHit2D hit = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if(hit.transform != null)
{
platforms.Add(hit.transform);
if(currentPlatform == hit.transform)
{
onSamePlatform = true;
}
}
}
if(!onSamePlatform)
{
foreach(Transform platform in platforms)
{
currentPlatform = platform;
lastPlatformPosition = currentPlatform.position;
}
}
}
void LateUpdate()
{
if(currentPlatform != null)
{
//Determine how far platform has moved
currentPlatformDelta = currentPlatform.position - lastPlatformPosition;
lastPlatformPosition = currentPlatform.position;
}
if(currentPlatform != null)
{
//Move with the platform
transform.position += currentPlatformDelta;
}
}
}
A problem arises when I try to modify the script with a touchable controller. I have googled many times and modified the script as I could, and still it gives me no result (btw, I'm new to Unity). Then I found a tutorial from a website about making a touch controller with a GUI Texture (TouchControls). I think that tutorial is easy to learn. Here is the script
using UnityEngine;
using System.Collections;
[RequireComponent(typeof (Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))]
public class TouchControls : MonoBehaviour {
// GUI textures
public GUITexture guiLeft;
public GUITexture guiRight;
public GUITexture guiJump;
private Animator anim;
// Movement variables
public float moveSpeed = 5f;
public float jumpForce = 50f;
public float maxJumpVelocity = 2f;
// Movement flags
private bool moveLeft, moveRight, doJump = false;
void Start ()
{
anim = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
// Check to see if the screen is being touched
if (Input.touchCount > 0)
{
// Get the touch info
Touch t = Input.GetTouch(0);
// Did the touch action just begin?
if (t.phase == TouchPhase.Began)
{
// Are we touching the left arrow?
if (guiLeft.HitTest(t.position, Camera.main))
{
Debug.Log("Touching Left Control");
moveLeft = true;
}
// Are we touching the right arrow?
if (guiRight.HitTest(t.position, Camera.main))
{
Debug.Log("Touching Right Control");
moveRight = true;
}
// Are we touching the jump button?
if (guiJump.HitTest(t.position, Camera.main))
{
Debug.Log("Touching Jump Control");
doJump = true;
}
}
// Did the touch end?
if (t.phase == TouchPhase.Ended)
{
// Stop all movement
doJump = moveLeft = moveRight = false;
}
}
// Is the left mouse button down?
if (Input.GetMouseButtonDown(0))
{
// Are we clicking the left arrow?
if (guiLeft.HitTest(Input.mousePosition, Camera.main))
{
Debug.Log("Touching Left Control");
moveLeft = true;
}
// Are we clicking the right arrow?
if (guiRight.HitTest(Input.mousePosition, Camera.main))
{
Debug.Log("Touching Right Control");
moveRight = true;
}
// Are we clicking the jump button?
if (guiJump.HitTest(Input.mousePosition, Camera.main))
{
Debug.Log("Touching Jump Control");
doJump = true;
}
}
if (Input.GetMouseButtonUp(0))
{
// Stop all movement on left mouse button up
doJump = moveLeft = moveRight = false;
}
}
void FixedUpdate()
{
//anim.SetFloat("Speed", Mathf.Abs);
// Set velocity based on our movement flags.
if (moveLeft)
{
rigidbody2D.velocity = -Vector2.right * moveSpeed;
}
if (moveRight)
{
rigidbody2D.velocity = Vector2.right * moveSpeed;
}
if (doJump)
{
// If we have not reached the maximum jump velocity, keep applying force.
if (rigidbody2D.velocity.y < maxJumpVelocity)
{
rigidbody2D.AddForce(Vector2.up * jumpForce);
} else {
// Otherwise stop jumping
doJump = false;
}
}
}
}
But I have no idea how to implement the script from the tutorial (TouchControls) and assign that to my player control script (PlayerCharacter). How can I combine both scripts so that a player can control it with a touchable control?
The best thing you can do is not to drag the touch controls from the touchcontrols tutorial to the playercontroller but the other way around, use the touchcontrols tutorial script as your template.
Since your playercontroller uses floats in its input such as moveleft = 50.0f; and the touchcontrols uses moveleft = true;
the scripts are very different from each other to just merge and work.
so from that in the touchcontrols leave the update function as it is,
and only update the fixedupate function with your controls logic since
the update void, is the condition controller for right, left, up & down so to speak.
and it will also handle the actual input of the touch.
the fixed update could then control some things that the playercontroller has such as
apply force when touching a tagged object or stuff like that.
and the update only does the input condition, good advice would be to wrap the update touch code in its own function so the update is not only touch but also other game logic related code.
You should search use copy the touch control script inside the player controller while changing the right parts. For example, instead of using Input.GetKeyDown you should use the Input.GetTouch but it depends on the game you are creating. You should pay attention to that code and change some parts