Click and Hold OnMouseDown Unity3D - unity3d

I want my OnMouseDown command to work only when the player presses over an object within the game. At the moment, the player can press anywhere and the timer will start. Is there a way to have the timer only start when they click and hold an object? To give you some context, I want an object to become inactive when the player clicks and holds over it.
Here is my code so far:
function Update ()
{
if (Input.GetMouseButton(0))
{
timer += Time.deltaTime;
}
if ( Input.GetMouseButtonUp(0))
{
timer = 0;
}
if(timer > 1)
{
gameObject.SetActive(false);
}
}

SOLUTION:
I used a Raycast in order to do this:
var ray: Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var hit : RaycastHit;
if (Input.GetMouseButton(0) && coll.Raycast(ray,hit,100))
{
timer += Time.deltaTime;
}
if ( Input.GetMouseButtonUp(0))
{
timer = 0;
}

Related

Unity3D for Google Cardboard

I have a VR Scene with a C# Script on the camera that allows the user to Click Once to move and again to stop.
public float speed = 1.0f;
public bool startedMoving = true;
public GameObject myCam;
// Update is called once per frame
void Update () {
if (startedMoving) {
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
// if(Input.GetButtonDown("Fire1")){
if (Input.GetMouseButton(0)){
startedMoving = !startedMoving;
}
}
What I want to know is how I can CLICK & HOLD to move Backwards..?
Thank you!
~ b
Use enum the represent the status of the mouse instead of startedMoving or multiple booleans that will make everything easier to implement. The comment in the code describes how it works.
using UnityEngine;
using System.Collections;
public class ClickAndHeld : MonoBehaviour
{
public GameObject myCam;
CLICK_MODE clickMode = CLICK_MODE.NO_CLICK;
MOVE_DIRECTION moveDir = MOVE_DIRECTION.IDLE;
public float speed = 1.0f;
//If down for 0.5 secods the it is considered Click and Hold instead of Click
float clickHoldDetectTime = 0.5f;
float clickCounter = 0; //Dont not change
void Start()
{
StartCoroutine(mover());
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
//If in NO_CLICK, set to CLICKED
if (clickMode == CLICK_MODE.NO_CLICK)
{
//Change the mode to CLICKED
clickMode = CLICK_MODE.CLICKED;
}
//If in CLICKED mode, start counting to clickHoldDetectTime
if (clickMode == CLICK_MODE.CLICKED)
{
clickCounter += Time.deltaTime; //Increment counter
//Check if we have reached the clickHoldDetectTime time
if (clickCounter > clickHoldDetectTime)
{
//Reset Counter
clickCounter = 0;
//Change the mode to CLICK_AND_HELD
clickMode = CLICK_MODE.CLICK_AND_HELD;
}
}
//If STILL down and the the current mode is CLICK_AND_HELD then do clickedAndHeldDown stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
clickedAndHeldDown();
}
}
else
{
//If released and the current mode is CLICKED then do clicked stuff
if (clickMode == CLICK_MODE.CLICKED)
{
clicked();
}
//If released and the current mode is CLICK_AND_HELD, change to RELEASED then do relased stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
//Change the mode to RELEASED
clickMode = CLICK_MODE.RELEASED;
mouseReleasedAfterBeingHeld();
}
//Reset each time mouse button is released
reset();
}
}
IEnumerator mover()
{
while (true)
{
if (moveDir == MOVE_DIRECTION.IDLE)
{
}
//Move Forward
if (moveDir == MOVE_DIRECTION.FORWARD)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
//Move Backward
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
yield return null;
}
}
private void clicked()
{
Debug.Log("CLICKED");
//If Idle, become Forward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.FORWARD;
}
//If forward, moves become idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If backward, moves become idle
else if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
private void clickedAndHeldDown()
{
Debug.Log("CLICKED AND HELD");
//If Idle, becomes backward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.BACKWARD;
}
}
//Called when released after being RELEASED from CLICKED_HELD
private void mouseReleasedAfterBeingHeld()
{
Debug.Log("RELEASED AFTER CLICKED AND HELD");
//If backward, move becomes idle
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If forward, move becomes idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
void reset()
{
clickMode = CLICK_MODE.NO_CLICK;
clickCounter = 0;
}
}
public enum CLICK_MODE
{
NO_CLICK, CLICKED, CLICK_AND_HELD, RELEASED
}
public enum MOVE_DIRECTION
{
IDLE, FORWARD, BACKWARD
}
Because you only have one trigger action you're going to have to implement something time based for toggling forward/backwards movement. For example, if you press and release the trigger quickly then forward walk could be toggled, but if you're holding the trigger after N length of time then walk backwards.
He's a practical example to get you starting.
Pressing and releasing the trigger within 300ms will toggle forward movement
Pressing and holding the trigger for longer than 300ms will begin backwards movement, releasing the trigger then will stop backwards movement
This is a theoretical example
public float speed = 1.0f;
bool triggerPressed = false;
float triggerHeldTime = 0f;
public bool movingForwards = false;
public bool movingBackwards = false;
void Update ()
{
// increment hold time if we're still holding trigger
if (Input.GetMouseButton(0) && triggerPressed)
triggerHeldTime += Time.deltaTime;
if (Input.GetMouseButton(0) && !triggerPressed)
{
// reset everything when trigger initially pressed
movingForards = false;
movingBackwards = false;
triggerHeldTime = 0f;
triggerPressed = true;
}
else if (!Input.GetMouseButton(0) && triggerPressed)
{
// upon trigger release
triggerPressed = false;
// if we are not moving backwards, toggle forwards movement
if(!movingBackwards)
movingForwards = !movingForwards;
// always reset backwards movement when we release the trigger
movingBackwards = false;
triggerHeldTime = 0f;
}
// if the trigger has been held for 300ms then move backwards
if(triggerHeldTime > 0.3f)
{
moveForwards = false;
moveBackwards = true;
}
// actually perform the movement
if (moveForwards)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
else if(moveBackwards)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
}

Infinite prefab spawn bug

I have a simple spawn script for my 2D game that i wrote, that i want to spawn an object after a specific period of time. I managed to get this to work but the one problem is that the object keeps spawning. I just want the object to spawn once not an infinite amount.
var myTimer : float = 5.0;
var thePrefab : GameObject;
function Update () {
if(myTimer > 0){
myTimer -= Time.deltaTime;
}
if(myTimer <= 0){
var instance : GameObject = Instantiate(thePrefab, transform.position, transform.rotation);
}
}
By shifting around your if statements, you can restrict your object to only spawning once:
var myTimer : float = 5.0;
var thePrefab : GameObject;
function Update () {
if(myTimer > 0){
myTimer -= Time.deltaTime;
if(myTimer <= 0){
var instance : GameObject = Instantiate(thePrefab, transform.position, transform.rotation);
}
}
}
Now, the object will only spawn if myTimer > 0 prior to the decrement, and myTimer <= 0 following the decrement - which only happens once.
Hope this helps! Let me know if you have any questions.

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);
}
}
}

Why my Players life disappear at once?

I am new in unity and I am developing game like Flippy Bird where if my player is collide with another object then one life of my player will disable and the collider is travel from one place to another place and there is so many colliders and the collider is little bit wide so when my player touch with that collider then its three life is disabled one by one in very short time.
I understand that when my player touch the same object again and again. So that players all life cut at the same time but i don't know how to solve this.
Code for Collision is below.
void OnTriggerEnter(Collider C){
if(C.gameObject.name == "DownCollider" || C.gameObject.name == "Cylinder"){
if(Life1.activeInHierarchy){
Life1.SetActive(false);
}
else if(Life2.activeInHierarchy){
Life2.SetActive(false);
}
else if(Life3.activeInHierarchy){
Life3.SetActive(false);
}
}
I just try this and it works for me..
void Update () {
Vector3 pos = transform.position;
pos.y -= 0.03f;
transform.localRotation = Quaternion.Euler(60,270,90);
transform.position = pos;
if(Input.GetMouseButton(0)){
transform.localRotation = Quaternion.Euler(72,90,-90);
pos.y += 0.1f;
transform.position = pos;
}
LifeT -= Time.deltaTime;
if(LifeT <= 0){
LifeTime = true;
LifeT = 5f;
}
}
void OnTriggerEnter(Collider C){
if(C.gameObject.name == "DownCollider" || C.gameObject.name == "Cylinder"){
print(LifeTime);
if(Life1.activeInHierarchy && LifeTime){
Life1.SetActive(false);
LifeTime = false;
}
else if(Life2.activeInHierarchy && LifeTime){
Life2.SetActive(false);
LifeTime = false;
}
else if(Life3.activeInHierarchy && LifeTime){
Life3.SetActive(false);
LifeTime = false;
}
}
Thanks for help KennethLJJ.
Regards,
Dharmesh

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