Unity3d how to reference swipe control from another script? - c#

I have tried every which way possible to get this to work with no success. I have a swipe script and a game/control script. I am trying to reference the swipe control in my control script as the means to control my character. So far I am getting only one error from within Unity.
Assets/RuinRunStarterKit/Scripts/csTempleRun.cs(307,25): error CS1501: No overload for method UpdatePlayer' takes0' arguments
I've tried adding TouchDetector.enTouchType within the parenthesis of UpdatePlayer but that gives me three errors rather than just one. I've contacted numerous people and visited numerous sites looking for answers but have failed to yield a working result. I am not educated in programming. I have only researched online to figure out how to do something as far as programming goes. The second script I have here is from an Asset I purchased on the Unity Asset Store. I have contacted them for support for adding swipe controls and they emailed me the touch script but failed to tell me how to implement it. I just want to play this game on my phone with swipe as the controls. This is for personal use. I would really really appreciate it if someone could help me achieve the desired results. Again, I want to be able to control the character using swipe. Thank you. Here are my scripts:
TouchDetector.cs;
using UnityEngine;
using System.Collections;
public class TouchDetector : MonoBehaviour {
public delegate void deTouchEvent
(enTouchType touchType);
public static event
deTouchEvent
evTouchEvent;
public enum enTouchType
{
SwipeLeft,
SwipeRight,
SwipeDown,
SwipeUp,
}
void Start ()
{
}
void Update ()
{
if (evTouchEvent == null)
return;
if (Input.GetKeyDown(KeyCode.UpArrow )) evTouchEvent(enTouchType.SwipeUp );
if (Input.GetKeyDown(KeyCode.DownArrow )) evTouchEvent(enTouchType.SwipeDown );
if (Input.GetKeyDown(KeyCode.LeftArrow )) evTouchEvent(enTouchType.SwipeLeft );
if (Input.GetKeyDown(KeyCode.RightArrow)) evTouchEvent(enTouchType.SwipeRight);
if (Input.touchCount > 0)
{
foreach (Touch t in Input.touches)
{
Vector3 swipe = t.deltaPosition * t.deltaTime;
if (swipe.y > 0.5f) evTouchEvent(enTouchType.SwipeUp );
if (swipe.y < -0.5f) evTouchEvent(enTouchType.SwipeDown );
if (swipe.x > 0.5f) evTouchEvent(enTouchType.SwipeRight);
if (swipe.x < -0.5f) evTouchEvent(enTouchType.SwipeLeft );
}
}
}
}
csTempleRun.cs;
void Update ()
{
UpdatePlayer();
if (m_player != null)
{
// Make the camera follow the player (if active)
SmoothFollow sF = (SmoothFollow)Camera.mainCamera.GetComponent(typeof(SmoothFollow));
sF.target = m_player.transform;
// Check for collisions with interactive objects
UpdateCoins();
UpdateMines();
// Dynamically update the track
CreateNewCellsIfNeeded(false);
}
}
private void UpdatePlayer(TouchDetector.enTouchType T)
{
// if the player is dead (replaced with ragdoll) then exit since none of this code should fire.
if (m_player == null)
{
return;
}
// Gradually increase the players' running speed, and update the animation to match.
m_playerRunSpeed += Time.deltaTime * 0.005f;
m_playerRunSpeed = Mathf.Clamp(m_playerRunSpeed, 0.5f, 3.0f);
m_player.animation["run"].speed = m_playerRunSpeed * 2.0f;
// ****************************************************************************************
// INPUT
// Player can only turn if they are not already sliding / jumping.
// Equally, sliding / jumping are mutually exclusive.
if (Input.GetKeyDown (KeyCode.LeftArrow)&& m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
if (m_playerDirection == enCellDir.North) m_playerNextDirection = enCellDir.West;
if (m_playerDirection == enCellDir.East ) m_playerNextDirection = enCellDir.North;
if (m_playerDirection == enCellDir.South) m_playerNextDirection = enCellDir.East;
if (m_playerDirection == enCellDir.West ) m_playerNextDirection = enCellDir.South;
}
if (Input.GetKeyDown(KeyCode.RightArrow) && m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
if (m_playerDirection == enCellDir.North) m_playerNextDirection = enCellDir.East;
if (m_playerDirection == enCellDir.East ) m_playerNextDirection = enCellDir.South;
if (m_playerDirection == enCellDir.South) m_playerNextDirection = enCellDir.West;
if (m_playerDirection == enCellDir.West ) m_playerNextDirection = enCellDir.North;
}
if (T==TouchDetector.enTouchType.SwipeDown && m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
m_playerSlide = 1.0f;
m_player.animation.Play("slide_fake");
}
if ((Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space)) && m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
AudioSource.PlayClipAtPoint(m_jumpAudio, m_player.transform.position);
m_playerJump = 1.0f;
m_playerYvel = 0.0f;
m_player.animation.Play("jump");
}
I hope I'm not doing anything wrong by posting this script but I feel I need to post this in order to get the help I need. You'll notice in the csTempleRun.cs script that I replaced one of the KeyCode calls with TouchDetector.enTouchType.SwipeDown. Yet I am still getting an error. Thank you in advance for anyone's help. Thank you for your time as well.

Look at your error - No overload for method UpdatePlayer' takes0' arguments. It means that you need to supply an additional data to your method. Which data you need to supply intellisense can tell you.

In your code:
void Update ()
{
UpdatePlayer();
...
You call UpdatePlayer() with zero arguments. However, UpdatePlayer needs an argument:
private void UpdatePlayer(TouchDetector.enTouchType T)
{
So, when you call UpdatePlayer(), you need to send an object of the type TouchDetector.enTouchType as parameter. That would be one of the following:
SwipeLeft
SwipeRight
SwipeDown
SwipeUp

Related

Unity script when my character hits the trashbin the item i picked up must be deleted

So i am making a level of unity: In this level you have to sort the garbage.
The player can move with the arrow keys, and can pick up trash with the E key. Then take it to the right trash can. I made a script that should make the character pickup the item and then he can go to the right trashbin and if he hits the trashbin the item will be destroyed, but it does not work and I have no idea what is wrong.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PickupItem : MonoBehaviour
{
public float pickupRange = 2f;
public LayerMask pickupLayer;
public AudioClip pickupSound;
public string[] pickupTags;
public AudioClip wrongBinSound;
public string[] trashBinTags;
public TextMeshProUGUI itemNameText;
private AudioSource audioSource;
private GameObject currentObject;
private bool holdingItem = false;
private void Start()
{
audioSource = GetComponent<AudioSource>();
}
private void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, pickupRange, pickupLayer))
{
foreach (string tag in pickupTags)
{
if (hit.collider.tag == tag && !holdingItem)
{
currentObject = hit.collider.gameObject;
if (Input.GetKeyDown(KeyCode.E))
{
StartCoroutine(Pickup());
}
break;
}
}
}
else
{
currentObject = null;
}
}
private void OnCollisionEnter(Collision collision)
{
foreach (string trashBinTag in trashBinTags)
{
if (collision.gameObject.tag == trashBinTag)
{
switch (currentObject.tag)
{
case "paper":
if (trashBinTag == "TrashbinPa")
{
Debug.Log("paper in vuilbak");
audioSource.PlayOneShot(pickupSound);
itemNameText.text = "";
holdingItem = false;
}
break;
case "glass":
if (trashBinTag == "TrashbinG")
{
Debug.Log("glass in vuilbak");
audioSource.PlayOneShot(pickupSound);
Destroy(currentObject);
itemNameText.text = "";
holdingItem = false;
}
break;
case "metal":
if (trashBinTag == "TrashbinM")
{
Debug.Log("metal in vuilbak");
audioSource.PlayOneShot(pickupSound);
Destroy(currentObject);
itemNameText.text = "";
holdingItem = false;
}
break;
case "plastic":
if (trashBinTag == "TrashbinP")
{
Debug.Log("plastic in vuilbak");
audioSource.PlayOneShot(pickupSound);
Destroy(currentObject);
itemNameText.text = "";
holdingItem = false;
}
break;
default:
audioSource.PlayOneShot(wrongBinSound);
break;
}
break;
}
}
}
IEnumerator Pickup()
{
if (currentObject != null)
{
Debug.Log("Object picked up");
yield return new WaitForSeconds(1);
audioSource.PlayOneShot(pickupSound);
currentObject.SetActive(false);
itemNameText.text = "Inventory: " + currentObject.name;
holdingItem = true;
}
}
}
My character settings:
enter image description here
One of mine Trashbin(Glass):
enter image description here
One of mine Trash items(Wine bottle):
enter image description here
I don't know what i'm doing wrong can someone help me?
I tried to debug but no outcome. I can pickup the item but i cannot hit the trashbin so it can delete the item. I use tags for the right trashbin which also use tags.
Alright, so let's take it one step at a the time. First of all, that code needs a lot of optimization as it's a FPS-drop nightmare.
private void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, pickupRange, pickupLayer))
{
foreach (string tag in pickupTags)
{
if (hit.collider.tag == tag && !holdingItem)
{
currentObject = hit.collider.gameObject;
if (Input.GetKeyDown(KeyCode.E))
{
StartCoroutine(Pickup());
}
break;
}
}
}
else
{
currentObject = null;
}
}
Here you are raycasting every frame regardless of the player wanting to pick up the trash or not (i.e. hitting the E key). This doesn't make much sense. As I said in my comment, this check if (Input.GetKeyDown(KeyCode.E)) should be a lot earlier.
Also, if the player has holdingItem == true, raycasting to search for additional trash doesn't really make sense if the player can only carry one trash at a time. So you can optimize that code out this way. I would even argue that holdingItem will cause conflicts since the same effect can be achieved by using currentObject != null, therefore, I'll recycle holdingItem.
Next, iterating through lists each frame, also adds overhead. If you see the break, you actually call it only if this condition if (hit.collider.tag == tag && !holdingItem) is fulfilled. That means that regardless of holding an item or pressing E, as long as the player stares at some trash, you will Raycast each frame, iterate through the list each frame and compare the tag.
I mentioned tag compare. Comparing tags as string also adds some overhead. Please see GameObject.CompareTag() as that is the proper way to efficiently compare tags. Also learn how conditions work, both for or as well as for and. In your case you chose the most inefficient way to compare:
if (hit.collider.tag == tag && !holdingItem)
Even if you would choose NOT to use CompareTag() (although you should use it), this will always be more efficient:
if (!holdingItem && hit.collider.tag == tag)
This is because if the player holds an item, the next condition is skipped. When using or and and clauses in conditions always use the least expensive and most common one first.
The else is also dodgy there. That means that if the player holds an object, that object will be set to null if a Raycast doesn't hit anything in range. This might be the reason why your trash destruction fails.
This should be better, I think:
private void Update()
{
if (currentObject == null && Input.GetKeyDown(KeyCode.E))
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, pickupRange, pickupLayer))
{
holdingItem = false; // you have a 1 second delay in Pickup()
// no delay here
foreach (string tag in pickupTags)
{
if (!holdingItem && hit.collider.gameObject.CompareTag(tag))
{
holdingItem = true; // stops overlaps
StartCoroutine(Pickup(hit.collider.gameObject));
break;
}
}
}
}
}
IEnumerator Pickup(GameObject trash)
{
if (holdingItem && trash != null && currentObject == null)
{
#if UNITY_EDITOR
// don't include this outside tests
Debug.Log(trash.tag + " picked up");
#endif
yield return new WaitForSeconds(1);
audioSource.PlayOneShot(pickupSound);
currentObject = trash;
currentObject.SetActive(false);
itemNameText.text = "Inventory: " + currentObject.name;
}
}
Next, let's look at the trash bin.
There is a ton of repeated code that can just be simplified away. Easier for maintenance too, not to mention bug fixes.
This is how I'd write OnCollisionEnter():
private void ThrowTrashAway()
{
#if UNITY_EDITOR
// don't include this outside tests
Debug.Log(currentObject.tag + " in vuilbak");
#endif
audioSource.PlayOneShot(pickupSound);
Destroy(currentObject);
currentObject = null;
itemNameText.text = "";
holdingItem = false;
}
private void OnCollisionEnter(Collision collision)
{
if (currentObject == null)
return; // don't execute anything
if ((collision.gameObject.CompareTag("TrashbinPa") && currentObject.CompareTag("paper"))
|| (collision.gameObject.CompareTag("TrashbinG") && currentObject.CompareTag("glass"))
|| (collision.gameObject.CompareTag("TrashbinM") && currentObject.CompareTag("metal"))
|| (collision.gameObject.CompareTag("TrashbinP") && currentObject.CompareTag("plastic")))
ThrowTrashAway();
else
audioSource.PlayOneShot(wrongBinSound);
}
Also keep in mind you don't destroy paper trash in your original code, like you do with other types of trash. So if you tested with paper, it wouldn't have worked anyway.
At first glance I'd say it's because of how you originally wrote the code in Update(). Of course this is also blind guessing since you haven't provided any debugging info regarding what steps the code executed in each branch on the stack nor did you tell us how each log call was or wasn't called. Regardless of whether you apply the suggestions, at least keep the concept in mind for further projects. Just because checking something in Update() is easier doesn't mean you have to do it there.
Still, as I said in my comment, the best way to really know why your code did not execute is a debugging session (not Debug.Log() calls, although they can help as well but they should never replace real debugging).
Let us know how it turned out.
I'm not entirely sure what your switch statement is doing, since currentObject gets disabled when it gets picked up (currentObject.SetActive(false);). By disabling it, the raycast in your Update() method will not find anything, and currentObject will be set to null every frame.
This will prevent any of your destruction code from running inside the OnCollisionEnter() method.
I would suggest either not disabling the currentObject, or pausing the raycast in Update() when an object is being held. This will allow the switch statement to run inside the collision method, and should destroy your object.

Why won't Unity SetActive execute within Input.GetButtonDown()?

I'm completely stumped by this one. I have a book in game and when you are looking in its general direction while within a certain distance of it and press the Action button (e or left mouse click), it's supposed to display a UI panel (bookPage). Here's my code for it.
void Update () {
Vector3 direction = player.transform.position - this.transform.position;
angle = Vector3.Angle (direction, player.transform.forward);
distance = direction.magnitude;
if (angle >= 160 && distance <= 2 && !bookPage.activeSelf) {
if(Input.GetButtonDown("Action")) {
bookPage.SetActive (true);
}
}
if (bookPage.activeSelf && Input.GetButtonDown("Action")) {
bookPage.SetActive (false);
}
}
This doesn't work. Specifically, the line to set the page to active doesn't work. If it's open, it will close correctly. If I copy and paste bookPage.SetActive (true);
anywhere within this method besides within if(Input.getButtonDown("Action")){}, it will make the bookPage active. If I put Debug.Log("message"); within that if statement though, it will show up in the console. It's just the one line that sets bookPage to active that isn't working. I have no idea why. I've tried moving it to a different method then calling it and doing the same but using a Coroutine. Neither worked. I also tried using other keys which did work, but I need it to work with the action key. It's also worth noting that the action key works in other usage. I already use it to open doors. Has anyone else run into a problem like this?
When you call SetActive(true), activeSelf will return true for your second condition which will invoke SetActive(false) immediately after.
Change this;
if (angle >= 160 && distance <= 2 && !bookPage.activeSelf)
{
if (Input.GetButtonDown("Action"))
{
bookPage.SetActive(true);
}
}
if (bookPage.activeSelf && Input.GetButtonDown("Action"))
{
bookPage.SetActive(false);
}
To this;
if (angle >= 160 && distance <= 2 && !bookPage.activeSelf)
{
if (Input.GetButtonDown("Action"))
{
bookPage.SetActive(true);
}
}
else if (bookPage.activeSelf && Input.GetButtonDown("Action"))
{
bookPage.SetActive(false);
}

Unity - Destroy the DoorController after finishing the task

I have scripted a controller for opening doors in a TopDown-Shooter.
I rotate pivot points around their local Y-Axis to open the door objects. The doors should stay open, so I do not need the Controller and the Controller object anymore. I want to destroy it after finishing its job.
My script looks this:
public class DoorController : MonoBehaviour
{
public Transform pivotLeftTransform; // the left pivot point
public Transform pivotRightTransform; // the right pivot point
int openAngle = 90; // how far should the door open up?
bool startOpen = false; // start opening?
float smooth = 2; // smooth rotation
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
startOpen = true; // when the Player triggers, start opening
}
}
void Update()
{
if (startOpen)
{
OpenDoor(pivotLeftTransform, openAngle);
OpenDoor(pivotRightTransform, -openAngle);
if (pivotLeftTransform.localRotation.y == openAngle && pivotRightTransform.localRotation.y == -openAngle) // when the doors are rotated, destroy this object
{
Destroy(gameObject);
}
}
}
private void OpenDoor(Transform pivotTransform, int rotationAngle)
{
Quaternion doorRotationOpen = Quaternion.Euler(0, rotationAngle, 0); // desired door rotation
pivotTransform.localRotation = Quaternion.Slerp(pivotTransform.localRotation, doorRotationOpen, smooth * Time.deltaTime); // rotate the door to the desired rotation
}
}
My Question is, how can I destroy the object. My code
if (pivotLeftTransform.localRotation.y == openAngle && pivotRightTransform.localRotation.y == -openAngle)
does not seem to work. After having the pivot point rotated to 90 or -90 degrees the statement still stays false. I also tried
pivotTransform.rotation.y
but it does not work neither. Which rotation do I need to pass in?
Thanks.
Two things wrong in your code:
1.Comparing floats
2.Using transform.localRotation or transform.rotation to check for angle.
You can solve this by using eulerAngles or localEulerAngles. Also for comparing floats, use >= instead of = as that may never be true.
Replace
if (pivotLeftTransform.localRotation.y == openAngle && pivotRightTransform.localRotation.y == -openAngle)
{
Destroy(gameObject);
}
with
if (pivotLeftTransform.localEulerAngles.y >= openAngle && pivotRightTransform.localRotation.y >= -openAngle)
{
Destroy(gameObject);
}
If you have problem with the answer above you have to troubleshoot it one by one. Separate the && and see which one is failing like this:
if (pivotLeftTransform.localEulerAngles.y >= openAngle)
{
Debug.Log("pivotLeftTransform");
}
if (pivotRightTransform.localRotation.y >= -openAngle)
{
Debug.Log("pivotRightTransform");
}
The right way to archieve this is adding a small tolerance value:
if (pivotLeftTransform.localEulerAngles.y >= openAngle - 0.1f && pivotRightTransform.localEulerAngles.y <= 360 - openAngle + 0.1f)
This may not be code clean but it works for the moment :)

OnMouseDrag and bool controller

I created 9 clone objects and U use OnMouseDrag function to move my objects.
First I drag object in the area zone and left button click to placed it in the map.
void OnMouseDrag(){
if(placed==false && placedArmyCounter<3){
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0f;
mousePos.x=Mathf.Round(mousePos.x);
mousePos.y=Mathf.Round(mousePos.y);
if( BoardManager.boardID==0 && mousePos.x>=0 && mousePos.x<=5 && mousePos.y>=0 && mousePos.y<=2){
transform.position=new Vector2((mousePos.x),(mousePos.y));
}
if( BoardManager.boardID==1 && mousePos.x>=0 && mousePos.x<=7 && mousePos.y>=0 && mousePos.y<=3){
transform.position=new Vector2((mousePos.x),(mousePos.y));
}
}
}
Left click
if(Input.GetMouseButtonDown(1) )
{
RaycastHit2D hit = Physics2D.Raycast (Camera.main.ScreenToWorldPoint((Input.mousePosition)), -Vector2.up);
if(hit.collider != null)
{
GameObject target = hit.collider.gameObject;
if(target.tag=="infantry"){
target.GetComponent<playerArmyMove>().Place();
}
if(target.tag=="archer"){
target.GetComponent<playerArmyMove>().Place();
}
if(target.tag=="horseman"){
target.GetComponent<playerArmyMove>().Place();
}
}
}
place function
public void Place(){
if(checkPlace==true){
placed=false;
}
if(checkPlace==false){
placed=true;
placedArmyCounter+=1;
}
}
When placed is true object cannot move again and placedArmyController using for starting game
By the way, I want only 3 objects can place in map area.
But there is a problem if I don't click left button , I can add a lot of objects in the map.And I don't want to happen like that.
I know I need another controller which checks "is there any object in map area and is placed or not".But if I add the controller in OnMouseDrag function any object can not move.
Is there any suggestion?
P.S : Don't care checkPlace boolean in place function it is about detect collision.

Touch Controls Unity2D

Im trying to use touch controls to move my character on a device such as an iPhone. So far I have had limited success. This code works but only with one of the buttons. I have both a left and right button and the left button worked until I added the right button. Now only the right button works. Any help would be appreciated.
foreach (Touch touch in Input.touches)
{
if(leftButton.guiTexture.HitTest(touch.position) && touch.phase != TouchPhase.Ended)
{
move = -1;
anim.SetFloat ("Speed", Mathf.Abs (move));
}
else if(rightButton.guiTexture.HitTest(touch.position) && touch.phase != TouchPhase.Ended)
{
move = 1;
anim.SetFloat ("Speed", Mathf.Abs (move));
}
else if((leftButton.guiTexture.HitTest(touch.position) && touch.phase == TouchPhase.Ended) &&
(rightButton.guiTexture.HitTest(touch.position) && touch.phase == TouchPhase.Ended))
{
move = 0;
}
}
An much easier alternative method for clicking would be
if(Input.GetMouseButtonDown(0))
{
//Your stuff here
}
remember to change input for clickable object (which i think is touch)
First, do a sanity check and verify that the left and right buttons are setup correctly on your component.
I'm not currently on a computer with unity to test everything, but there is a lot of redundancy here, we can clean it up to make debugging the problem easier. Another red flag is I don't see move being set to 0 before the input check, so I'll add that. Try this code and see if you are still seeing the problem, and perhaps you will be able to better debug with monodevelop what is happening.
move = 0;
bool isLeftPressed = false;
bool isRightPressed = false;
foreach (Touch touch in Input.touches)
{
// Only process touches that aren't in the ended phase
if (touch.phase == TouchPhase.Ended)
return;
if (leftButton.guiTexture.HitTest(touch.position))
isLeftPressed = true;
if (rightButton.guiTexture.HitTest(touch.position))
isRightPressed = true;
}
if (isLeftPressed && isRightPressed)
{
// Do nothing when both are pressed (move already set to 0)
}
else if (isLeftPressed)
{
move = -1;
}
else if (isRightPressed)
{
move = 1;
}
anim.SetFloat ("Speed", Mathf.Abs (move));
I made a few assumptions about what you were trying to do with the check if both left and right are pressed. Rather than setting the move value in the foreach loop, we just set flags so that after processing each touch we can see which buttons are being pressed (If finger 0 is touching one, and finger 1 is touching the other, I assume that means you want there to be no movement?)

Categories

Resources