Unity | Multitouch with phics2D Collider - unity3d

I created the sprites with images on my scene and i made work like buttons. All i want is that the all buttons are working simultaneously like multitouch screen. The code below is what i've done from now on. I use the TouchList which have gameobjects. I supposed the TouchList.Count would increase. However, the TouchList.Counts always show (number)1.
I definitely can't touch two gameObjects in same time because the state of first touched gameobject is changed to "Exit". How can i add touched gameObjects in TouchList?
Please let me know how can i fix this code.
void Update () {
if (Input.GetMouseButton(0) || Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0)) {
touchesOld = new GameObject[touchList.Count];
touchList.CopyTo(touchesOld);
touchList.Clear();
Vector2 pos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
RaycastHit2D hit1 = Physics2D.Raycast(pos, Vector2.zero);
//foreach (Touch touch in Input.touches) {
if (hit1.collider != null) {
GameObject recipient = hit1.transform.gameObject;
touchList.Add(recipient);
//Debug.Log ("recipient : " + hit1.transform.gameObject);
Debug.Log ("I'm hitting "+hit1.collider.name);
Debug.Log ("touchList.Count : " + touchList.Count);
//recipient.SendMessage("OnColliderHit",hit1.point,SendMessageOptions.DontRequireReceiver);
if (Input.GetMouseButtonDown(0)) {
recipient.SendMessage("OnTouchDown",hit1.point,SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButtonUp(0)) {
recipient.SendMessage("OnTouchUp",hit1.point,SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButton(0)) {
recipient.SendMessage("OnTouchStay",hit1.point,SendMessageOptions.DontRequireReceiver);
}
}
//}
foreach (GameObject g in touchesOld) {
if (!touchList.Contains(g)) {
g.SendMessage("OnTouchExit",hit1.point,SendMessageOptions.DontRequireReceiver);
}
}
}
}

This is my modified code. It works well.:-)
void Update () {
if (Input.GetMouseButton(0) || Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0)) {
touchesOld = new GameObject[touchList.Count];
touchList.CopyTo(touchesOld);
touchList.Clear();
foreach (Touch touch in Input.touches) {
Debug.Log ("touch.position : " + touch.position.ToString());
Vector2 pos = Camera.main.ScreenToWorldPoint(touch.position);
RaycastHit2D hit1 = Physics2D.Raycast(pos, Vector2.zero);
if (hit1.collider != null) {
GameObject recipient = hit1.transform.gameObject;
touchList.Add(recipient);
//Debug.Log ("recipient : " + hit1.transform.gameObject);
Debug.Log ("I'm hitting "+hit1.collider.name);
Debug.Log ("touchList.Count : " + touchList.Count);
//recipient.SendMessage("OnColliderHit",hit1.point,SendMessageOptions.DontRequireReceiver);
if (Input.GetMouseButtonDown(0)) {
recipient.SendMessage("OnTouchDown",hit1.point,SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButtonUp(0)) {
recipient.SendMessage("OnTouchUp",hit1.point,SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButton(0)) {
recipient.SendMessage("OnTouchStay",hit1.point,SendMessageOptions.DontRequireReceiver);
}
}
}
foreach (GameObject g in touchesOld) {
if (!touchList.Contains(g)) {
g.SendMessage("OnTouchExit",SendMessageOptions.DontRequireReceiver);
}
}
}
}

Related

How to make play and pause button on Augmented Reality (Vuforia) video playback in Unity?

There is a problem on my project that when it plays the video play automatically. How I want to make the video play and pause in Unity. I'm using Unity 2019.3.5f1 and Vuforia. Is there any tutorial about how to make video playback AR can play and pause?
I try this code but it doesn't work. I don't know why?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;
using UnityEngine.Video;
public class PlayControl : MonoBehaviour, ITrackableEventHandler
{
public GameObject videoplayer, Playvideo_button, Pausevideo_button, Stopvideo_button;
protected TrackableBehaviour mTrackableBehaviour;
public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus)
{
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
if (mTrackableBehaviour.TrackableName == "Video_marker")
{
videoplayer.GetComponent<VideoPlayer>().Play();
}
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
videoplayer.GetComponent<VideoPlayer>().Stop();
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
}
}
// Start is called before the first frame update
void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if(mTrackableBehaviour)
{
mTrackableBehaviour.RegisterTrackableEventHandler(this);
}
}
protected virtual void OnTrackingFound()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Enable rendering:
foreach (var component in rendererComponents)
component.enabled = true;
// Enable colliders:
foreach (var component in colliderComponents)
component.enabled = true;
// Enable canvas':
foreach (var component in canvasComponents)
component.enabled = true;
}
protected virtual void OnTrackingLost()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Disable rendering:
foreach (var component in rendererComponents)
component.enabled = false;
// Disable colliders:
foreach (var component in colliderComponents)
component.enabled = false;
// Disable canvas':
foreach (var component in canvasComponents)
component.enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//case 1
if (hit.collider.tag == "Playvideo")
{
videoplayer.GetComponent<VideoPlayer>().Play();
Playvideo_button.SetActive(false);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(true);
}
//case 2
if (hit.collider.tag == "Stopvideo")
{
videoplayer.GetComponent<VideoPlayer>().Stop();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(false);
}
//case 3
if (hit.collider.tag == "Pausevideo")
{
videoplayer.GetComponent<VideoPlayer>().Pause();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(false);
Stopvideo_button.SetActive(true);
}
}
}
}
}
It's not really clear where does this script runs in your project. The best way to make sure your hits are in the right place is to add the script to the buttons, which I see that you didn't. Did you make sure your Raycast reaches the right button? you can define a maxDistance to your Physics.Raycast that may be a great help here. Also in your "if" statements, I would check if there is a collision first and then check for the tag, something like this:
if (Physics.Raycast(ray, out hit, 900.0f))
{
if (hit.transform != null)
{
if (GameObject.ReferenceEquals(hit.transform.gameObject, playButtonGameObject))
{
videoplayer.GetComponent<VideoPlayer>().Play();
Playvideo_button.SetActive(false);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(true);
}
else if (GameObject.ReferenceEquals(hit.transform.gameObject, stopButtonGameObject))
{
videoplayer.GetComponent<VideoPlayer>().Stop();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(false);
}
else if (GameObject.ReferenceEquals(hit.transform.gameObject, pauseButtonGameObject))
{
videoplayer.GetComponent<VideoPlayer>().Pause();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(false);
Stopvideo_button.SetActive(true);
}
}
}

How to fix "gravity issue in unity AR project"

Project: Augmented game (vuforia)
I have a plane over which a ball resides.
The plane has rigid body and mesh collider on it.
The ball has a sphere collider and rigid body on it with gravity turned on.
As i play the game,the ball falls through the plane and keeps on falling.
I want the ball to stay on the plane so that i can control it with touch input.
I had this problem and I solved using the I TrackableEventHandler.
Look at this script:
using System.Collections;
using UnityEngine;
using Vuforia;
public class MarkerController: MonoBehaviour, ITrackableEventHandler
{
private TrackableBehaviour mTrackableBehavior;
// Start is called before the first frame update
void Start()
{
mTrackableBehavior = GetComponent<TrackableBehaviour>();
if (mTrackableBehavior)
{
mTrackableBehavior.RegisterTrackableEventHandler(this);
}
}
public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus)
{
if(newStatus == TrackableBehaviour.Status.DETECTED || newStatus == TrackableBehaviour.Status.TRACKED || newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
OnTrackingFound();
} else
{
OnTrackingLost();
}
}
private void OnTrackingFound()
{
Renderer[] rendererComponents = GetComponentsInChildren<Renderer>();
Collider[] colliderComponents = GetComponentsInChildren<Collider>();
for (int i = 0; i < this.transform.GetChildCount(); i++)
{
Debug.Log("Activating the children");
this.transform.GetChild(i).gameObject.SetActive(true);
}
foreach(Renderer component in rendererComponents)
{
component.enabled = true;
}
foreach(Collider component in colliderComponents)
{
component.enabled = true;
}
Debug.Log("Tracking of " + mTrackableBehavior.TrackableName + " found");
}
private void OnTrackingLost()
{
Renderer[] rendererComponents = GetComponentsInChildren<Renderer>();
Collider[] colliderComponents = GetComponentsInChildren<Collider>();
for (int i = 0; i < this.transform.GetChildCount(); i++)
{
Debug.Log("Deactivating children");
this.transform.GetChild(i).gameObject.SetActive(false);
}
foreach (Renderer component in rendererComponents)
{
component.enabled = false;
}
foreach (Collider component in colliderComponents)
{
component.enabled = false;
}
Debug.Log("Tracking of " + mTrackableBehavior.TrackableName + " lost");
}
}
In this class, I've only activated the components when the tracking of the markers is found! Otherwise it will be deactivated, and when the tracking is found again, then it will be displayed as the way it was before losing track.
I've added this script to the ARCamera component. Works fine here!

AudioSource.Play() not working in Enumerator

I have an Enumerator for the effects played when you shoot a gun. It is:
private IEnumerator ShotEffect()
{
gunAudio.Play();
laserLine.enabled = true;
yield return shotDuration;
laserLine.enabled = false;
}
When I take the gunAudio.Play() out, the code works fine. However, when I add it in, the sound does not play and the line doesn't disable. I assume there is a problem with the shotDuration?
The variable gunAudio is given the audio component in start, and shotDuration is a wait for seconds.
EDIT:
Also, if I set it to play on awake, it plays. Therefore I think there is a problem with the code, not the component.
Here is where I call the Enumerator:
if (Input.GetKey(KeyCode.Mouse0) && Time.time > nextFire)
{
torsoDamage = (int)Random.Range(50f, 70f);
legDamage = (int)Random.Range(20f, 30f);
handDamage = (int)Random.Range(5f, 15f);
nextFire = Time.time + fireRate;
StartCoroutine (ShotEffect());
Vector3 rayOrigin = fpsCam.ViewportToWorldPoint (new Vector3(0.5f, 0.5f, 0.0f));
RaycastHit hit;
laserLine.SetPosition (0, gunEnd.position);
if (Physics.Raycast (rayOrigin, fpsCam.transform.forward, out hit, weaponRange))
{
laserLine.SetPosition (1, hit.point);
if (enemyAi.enemy_currentHealth != null)
{
if (hit.collider.gameObject.tag == "head")
{
enemyAi.Damage(100);
}
if (hit.collider.gameObject.tag == "torso")
{
enemyAi.Damage(torsoDamage);
}
if (hit.collider.gameObject.tag == "leg" || hit.collider.gameObject.tag == "arm")
{
enemyAi.Damage(legDamage);
}
if (hit.collider.gameObject.tag == "hand" || hit.collider.gameObject.tag == "foot")
{
enemyAi.Damage(handDamage);
}
}
if (hit.rigidbody != null)
{
hit.rigidbody.AddForce (-hit.normal * hitForce);
}
}
else
{
laserLine.SetPosition (1, gunEnd.position + (fpsCam.transform.forward * weaponRange));
}
}
I fixed it - there was some weird problem with another variable that was being called from another script.
The code works fine now.

How to show a tracking line from where the model is placed in Augmented Reality?

I am looking to show a line in my app from where the model is placed so that the user knows position where the model is kept in real world. When user changes device camera away from model the line gets turned on to show where the model is. Similarly it turns off when model is detected. I have attached images to show from a similar app white dotted lines show the path. Notice how the lines disappear when the model is detected.
LineRenderer lins;
public GameObject Lineprefab;
private GameObject newline;
public Transform startpoint;
public Renderer m_rend1;
bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
{
List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);
if (hitResults.Count > 0 && check==true)
{
foreach (var hitResult in hitResults)
{
Debug.Log ("Got hit!");
//obj.Hideplane();
Genplanes.SetActive(false);
if (Select == 0) {
Debug.Log("hit-zero!");
Instantiate(Instaobj[0], ForSelect);
check = false;
}
if (Select == 1) {
Debug.Log("hit-one!");
Instantiate(Instaobj[1], ForSelect);
check = false;
}
if (Select == 2) {
Debug.Log("hit-two!");
Instantiate(Instaobj[2], ForSelect);
check = false;
}
m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
obj.StopPlaneTracking();
}
}
return false;
}
private void Start()
{
spawngenerator();
newline.SetActive(false);
m_rend1 = GetComponent<MeshRenderer>();
}
void spawngenerator()
{
GameObject newline = Instantiate(Lineprefab);
lins = newline.GetComponent<LineRenderer>();
}
private void LateUpdate()
{
lins.SetPosition(0, startpoint.position);
lins.SetPosition(1, m_HitTransform.position);
if( m_rend1.isVisible==true)
{
Debug.Log("Render is Visible");
newline.SetActive(false);
}
else if( m_rend1.isVisible==false)
{
newline.SetActive(true);
Debug.Log("It is InVisible");
Debug.Log("Render is InVisible");
}
}
void Update () {
#if UNITY_EDITOR //we will only use this script on the editor side, though there is nothing that would prevent it from working on device
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
//we'll try to hit one of the plane collider gameobjects that were generated by the plugin
//effectively similar to calling HitTest with ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent
if (Physics.Raycast (ray, out hit, maxRayDistance, collisionLayer)) {
//we're going to get the position from the contact point
m_HitTransform.position = hit.point;
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
//and the rotation from the transform of the plane collider
m_HitTransform.rotation = hit.transform.rotation;
}
}
#else
if (Input.touchCount > 0 && m_HitTransform != null )
{
var touch = Input.GetTouch(0);
if ((touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved) && !EventSystem.current.IsPointerOverGameObject(touch.fingerId))
{
var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
ARPoint point = new ARPoint {
x = screenPosition.x,
y = screenPosition.y
};
// prioritize reults types
ARHitTestResultType[] resultTypes = {
//ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingGeometry,
ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent,
// if you want to use infinite planes use this:
//ARHitTestResultType.ARHitTestResultTypeExistingPlane,
//ARHitTestResultType.ARHitTestResultTypeEstimatedHorizontalPlane,
//ARHitTestResultType.ARHitTestResultTypeEstimatedVerticalPlane,
//ARHitTestResultType.ARHitTestResultTypeFeaturePoint
};
foreach (ARHitTestResultType resultType in resultTypes)
{
if (HitTestWithResultType (point, resultType))
{
return;
}
}
}
}
#endif
}
.
First, I 'd start with checking if the model is within the bounding box of the camera https://docs.unity3d.com/ScriptReference/Renderer-isVisible.html
if the object is not visible (isVisible == false), create a line renderer from object position to wherever it should end.
The end point could be a camera child place just in front of it, so it looks like it starts from the user to the object.

Unity 2D: My laser script is getting stuck on an if statement and I don't know why

I've been making a laser in my 2D platformer for the past day. I've made the arm follow to cursor perfectly however on the script for the weapon it self doesn't work. Here is my code
using UnityEngine;
using System.Collections;
public class Weapon : MonoBehaviour {
public float fireRate = 0;
public float Damage = 10;
public LayerMask whatToHit;
float timeToFire = 0;
Transform firePoint;
// Use this for initialization
void Awake () {
firePoint = transform.FindChild ("FirePoint");
if (firePoint == null) {
Debug.LogError ("No firePoint");
}
}
// Update is called once per frame
void Update () {
if (fireRate == 0) {
if (Input.GetButtonDown ("Fire1")) {
Shoot();
}
}
else {
if (Input.GetButton ("Fire1") && Time.time > timeToFire) {
timeToFire = Time.time + 1/fireRate;
Shoot();
}
}
}
void Shoot () {
Debug.Log ("Works");
Vector2 mousePosition = new Vector2 (Camera.main.ScreenToWorldPoint (Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 firePointPosition = new Vector2 (firePoint.position.x, firePoint.position.y);
RaycastHit2D hit = Physics2D.Raycast (firePointPosition, mousePosition-firePointPosition, 100, whatToHit);
Debug.DrawLine (firePointPosition, (mousePosition-firePointPosition)*100, Color.cyan);
Debug.Log ("Works 2");
if (hit.collider != null) {
Debug.Log ("Work 3");
Debug.DrawLine (firePointPosition, hit.point, Color.red);
Debug.Log ("We hit " + hit.collider.name + " and did " + Damage + " damage.");
}
}
}
The if statement in void Shoot isn't working. The first two debug messages in void Shoot show up in the log however the two in the if statement don't and I have no idea why. Can anyone help?