Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by zstanzbose · May 14, 2018 at 03:51 PM · uimovementlightingplayereventsystem

Having an issue blocking UI taps from passing through the UI into a gameobject.

Hey guys, I've done a ton of searches on this and I've read all the forums on this, but I'm fairly new to Unity so most of the stuff is a little over my head. Here's my setup: I have a 2D click-to-move adventure game that's being developed for iPad. The player taps the ground and the character moves to that location. I was using the UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject()) to block UI taps from making the player character start wandering, but when the game is actually built to the iPad, it doesn't work at all. Every time the UI is touched, the player's character move, and it's really impacting the game. I'm going to attach my player movement script and maybe you guys could help me figure out how to improve it.

using UnityEngine; using System.Collections;

public class PlayerTest : MonoBehaviour {

  public Animator animator;
  public Vector2 target = new Vector2();
  public Vector2 direction = new Vector2();
  public Vector2 position = new Vector2();
  public Vector2 movement = new Vector2();
  Rigidbody2D rb2D;
  public float speed = 2.0f;
 
  void Start()
  {
      animator = gameObject.GetComponent<Animator>();   
      rb2D = GetComponent<Rigidbody2D>();
  }
  void FixedUpdate()
  {
      position = gameObject.transform.position;
      if (Input.GetMouseButtonDown(0) && !UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
      {
          target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
          Debug.Log("Click");
      }

      if (target != Vector2.zero && (target - position).magnitude >= 0.1)
      {
          direction = (target - position).normalized;

          movement.x = (direction.x * speed * Time.deltaTime);
          movement.y = (direction.y * speed * Time.deltaTime);

          rb2D.velocity = movement;
         

          //gameObject.transform.position = new Vector3((direction.x * speed * Time.deltaTime),(direction.y * speed * Time.deltaTime),0);
          //gameObject.transform.position.y += (direction.y * speed * Time.deltaTime);

          animator.SetBool("isMoving", true);
          animator.SetFloat("moveX", direction.x);
          animator.SetFloat("moveY", direction.y);
      }
      else
      {
          direction = Vector2.zero;
          rb2D.velocity = Vector2.zero;
          animator.SetBool("isMoving", false);
      }
  }}
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Vicarian · May 14, 2018 at 04:23 PM

UI elements are GameObjects as well. So IsPointerOverGameObject() will return true even for UI elements. Switch to using a Physics2D.Raycast. The origin point will be your tap location on the screen (Use a ScreenToWorld call), and the direction will be into the scene (most likely forward, not sure with 2D games). Tag the environment as "Ground" and when you Raycast against it, check the tag for Ground, then move if it is. If you need help writing the code, reply back here.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image zstanzbose · May 14, 2018 at 05:53 PM 0
Share

I could use some help writing the code, I've never used a Raycast before.

avatar image
0

Answer by Vicarian · May 14, 2018 at 10:17 PM

Sorry, had work come up.

Actually, you don't have to use a direct Raycast call after all. Here's what you do:


  • Make sure you have an EventSystem somewhere in your scene (search for it)

  • If you don't, highlight your scene in the Hierarchy, right click, GameObject > UI > EventSystem

  • Add a Physics2DRaycaster to your scene camera (should be your MainCamera)

  • Create the GroundMove script below

  • Highlight all ground objects in your scene

  • Click the Add Component button in the inspector and search for GroundMove

  • Double Click the script

  • Make sure to overwrite your PlayerTest file with the one I provided


You'll need to overwrite your PlayerTest file with the following:

 using UnityEngine;

 public class PlayerTest : MonoBehaviour {
     public Animator animator;
     public bool     needToMove;
     public float    timeMoveNeeded;
     public Vector2  direction = new Vector2();
     public Vector2  position = new Vector2();
     public Vector2  movement = new Vector2();
     public Vector2  target   = new Vector2();
     Rigidbody2D rb2D;
     public float speed = 2.0f;
     
     void Start() {
         animator = gameObject.GetComponent<Animator>();   
         rb2D = GetComponent<Rigidbody2D>();
 
         foreach (GroundMove gm in FindObjectsOfType<GroundMove>())
             gm.RaiseGroundClicked += HandleGroundClicked;
     }
 
     void FixedUpdate() {
         if (needToMove)
             transform.position = Vector2.Lerp(transform.position, target, speed * Time.fixedDeltaTime);
 
         if ((target - (Vector2)transform.position).magnitude <= 0.1f)
             needToMove = false;
     }
 
     void HandleGroundClicked(object sender, Vector2EventArgs e)
     {
         target = e.Data;
 
         if ((target - position).magnitude >= 0.1)
         {
             needToMove = true;
             direction  = (target - position).normalized;
 
             movement.x = (direction.x * speed * Time.deltaTime);
             movement.y = (direction.y * speed * Time.deltaTime);
 
             animator.SetBool("isMoving", true);
             animator.SetFloat("moveX", direction.x);
             animator.SetFloat("moveY", direction.y);
         }
     }
 }


 using UnityEngine;
 using UnityEngine.EventSystems;
 using System;
 public class GroundMove : MonoBehaviour, IPointerDownHandler {
     public event EventHandler<Vector2EventArgs> RaiseGroundClicked;
     public void OnPointerDown(PointerEventData data)
     {
         OnRaiseGroundClicked(new Vector2EventArgs(data.pointerCurrentRaycast.worldPosition));
     }
 
     protected virtual void OnRaiseGroundClicked(Vector2EventArgs e)
     {
         EventHandler<Vector2EventArgs> handler = RaiseGroundClicked;
 
         if (handler != null)
             handler(this, e);
     }
 }
 
 public class Vector2EventArgs : EventArgs {
     Vector2 m_data;
 
     public Vector2EventArgs(Vector2 data)
     {
         m_data = data;
     }
 
     public Vector2 Data { get { return m_data; } }
 }



Ok, what's all that do?

Basically, I don't know how many ground objects you have, so I made an event handler with a custom event argument type. When you click any ground objects, you use the IPointerDown event (provided by the EventSystem in Unity) to raise a custom event (GroundMove.RaiseGroundClicked) which reports the world location of the point that was clicked. The player object continually listens for any data to come up from these scripts (the event registration in PlayerTest.Start When data appears (the event is being handled) the player reacts to the click by beginning to move. It obviates the need for FixedUpdate in this case, so rather than checking each frame to see whether the user has interacted with the game, the player object is happy to sit there until the user actually does something. Neat, huh?


EDIT Switched to a Lerp. Setting velocity directly on rigidbodies I think isn't correct practice - need to look into it. I think correct practice is to use the AddForce methods, but I'm not terribly sure. The new code in PlayerTest gets you moving.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image zstanzbose · May 15, 2018 at 05:47 PM 0
Share

So I spent some time this afternoon trying the solution and I can't seem to get it to work. The player character doesn't move at all, even after switching out the deltaTime for the FixedUpdate. Here's the new movement script.

using System.Collections;

using System.Collections.Generic; using UnityEngine;

public class PlayerTest_ : $$anonymous$$onoBehaviour {

 public Animator animator;
 public Vector2 direction = new Vector2();
 public Vector2 position = new Vector2();

 public Vector2 movement = new Vector2();
 Rigidbody2D rb2D;
 Vector2EventArgs e;

 public float speed = 2.0f;
 bool needTo$$anonymous$$ove = false;
 Vector2 target;

 void Start()
 {
     animator = gameObject.GetComponent<Animator>();
     rb2D = GetComponent<Rigidbody2D>();

     // Subscribe to the Ground$$anonymous$$ove EventHandler
     foreach (Ground$$anonymous$$ove gm in FindObjectsOfType<Ground$$anonymous$$ove>())
         gm.RaiseGroundClicked += HandleGroundClicked;
 }

 void OnDestroy()
 {
     // EventHandlers are memory locations, so we need to return the 
     // memory back to the system when this is destroyed
     foreach (Ground$$anonymous$$ove gm in FindObjectsOfType<Ground$$anonymous$$ove>())
         gm.RaiseGroundClicked -= HandleGroundClicked;
 }

 void HandleGroundClicked(object sender, Vector2EventArgs e)
 {
     target = e.Data;
     needTo$$anonymous$$ove = true;
 }

 private void FixedUpdate()
 {
     if (!needTo$$anonymous$$ove)
         return;

     Vector2 target;

     position = gameObject.transform.position;
     target = e.Data;

     if (target != Vector2.zero && (e.Data - position).magnitude >= 0.1)
     {
         direction = (target - position).normalized;
         movement.x = (direction.x * speed * Time.deltaTime);
         movement.y = (direction.y * speed * Time.deltaTime);
         rb2D.velocity = movement;

         animator.SetBool("is$$anonymous$$oving", true);
         animator.SetFloat("moveX", direction.x);
         animator.SetFloat("moveY", direction.y);
     }
     else
     {
         direction = Vector2.zero;
         rb2D.velocity = Vector2.zero;
         animator.SetBool("is$$anonymous$$oving", false);
     }

     needTo$$anonymous$$ove = false;
 }

 

}

The Ground$$anonymous$$ove script is attached to the ground objects. $$anonymous$$y EventSystem has the Event System script and Standalone Input $$anonymous$$odule Script attached. Any advice is welcomed, and thank you for everything so far.

avatar image Vicarian zstanzbose · May 15, 2018 at 06:36 PM 0
Share

I'll take a look at it when I get home. The small test I did might not have been good enough.

avatar image Vicarian Vicarian · May 15, 2018 at 11:13 PM 0
Share

Before I $$anonymous$$r into the code, did you add a collider of any sort to the ground objects? I forgot to mention that.

Show more comments
avatar image
0

Answer by unity_BGmJcdED5Dqjfw · May 16, 2018 at 01:22 AM

You could also make a layermask for the UI elements and when using RayCastHit pass in the layermask to check against eg: RaycastHit(start vector*the point of origin for the click*, out ray*the ray that is being cast*, layermask) and it will only return the gameobjects hit on that layer. Then you simply need to set the layer of the UI elements to match that of the layer mask you declared. For more info on this I would recommend watching: this

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Vicarian · May 16, 2018 at 01:37 AM 0
Share

Also a good approach, if you need to raycast against more than one thing, since the Physics2D raycaster gets everything in its mask.

avatar image zstanzbose · May 16, 2018 at 06:30 PM 0
Share

I think the video link might be broken, I understand what you're saying in concept, but I'm not sure how to set that up tangibly.

avatar image unity_BGmJcdED5Dqjfw zstanzbose · May 19, 2018 at 01:46 AM 0
Share

https://youtu.be/SrCUO46jcxk

avatar image unity_BGmJcdED5Dqjfw unity_BGmJcdED5Dqjfw · May 19, 2018 at 01:47 AM 0
Share

This one should work sorry posting from my phone

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

202 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Move Slider-value to middle value when released 1 Answer

Having trouble with a basic movement script. 2 Answers

Player Movement Problems. 1 Answer

Which UI events propagate? 0 Answers

unity player keeps rotate when using joystick as inbut 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges