Unity 5 Fixed Update - c#

In my project written in Unity 5, I am performing the object touch operation with raycast. But, since my object is moving, sometimes raycast cannot reach to my when I touch. As a solution, using fixed update, I set the Fixed Timestep from 0.02 to 0.01 on the project settings. However, at this time, it behaves as if I were touching twice and it receives two touches. I should not use update function and I need to do this using fixed update. How can I solve the problem?
Below is my code:
void FixedUpdate()
{
if (PlayerPrefs.GetInt ("oyunsonu") == 0) {
// Code for OnMouseDown in the iPhone. Unquote to test.
RaycastHit hit = new RaycastHit ();
for (int i = 0; i < Input.touchCount; ++i) {
if (Input.GetTouch (i).phase.Equals (TouchPhase.Began)) {
Ray ray = Camera.main.ScreenPointToRay (Input.GetTouch (i).position);
touchY = Input.GetTouch (i).position.y;
if (Physics.Raycast (ray, out hit)) {
//Debug.Log (hit.transform.gameObject.name.ToString ());
GameObject myBallObject;
myBallObject = GameObject.FindWithTag ("Ball");
Instantiate (effect, myBallObject.transform.position, transform.rotation);
GetComponent<AudioSource> ().PlayOneShot (saundFile [3], 1);
//TextAnimation.Show ();
TouchObjectScript myTouchObjectScript = myBallObject.GetComponent<TouchObjectScript> ();
myTouchObjectScript.BallForce (hit.transform.gameObject.tag.ToString (), touchY, screenHeight);
//PlayerPrefs.SetInt ("aaa", 0);
}
}
}
}
}

You use Update() to detect input or move non physics/rigidbody objects. You use FixedUpdate() to move physics object. Watch UPDATE AND FIXEDUPDATE video from Unity.
Doing GameObject.FindWithTag("Ball"); each time there is touch and raycast is not good. Constantly checking PlayerPrefs.GetInt("oyunsonu") is not good either. Cache your variables if they will be used in a loop multiple times. Below is your fixed code.
AudioSource myAudio;
GameObject myBallObject;
TouchObjectScript myTouchObjectScript;
int oyunsonu = 0;
void Start()
{
myAudio = GetComponent<AudioSource>();
myBallObject = GameObject.FindWithTag("Ball");
myTouchObjectScript = myBallObject.GetComponent<TouchObjectScript>();
oyunsonu = PlayerPrefs.GetInt("oyunsonu");
}
void Update()
{
if (oyunsonu == 0)
{
// Code for OnMouseDown in the iPhone. Unquote to test.
RaycastHit hit = new RaycastHit();
for (int i = 0; i < Input.touchCount; ++i)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
touchY = Input.GetTouch(i).position.y;
if (Physics.Raycast(ray, out hit))
{
//Debug.Log (hit.transform.gameObject.name.ToString ());
Instantiate(effect, myBallObject.transform.position, transform.rotation);
myAudio.PlayOneShot(saundFile[3], 1);
//TextAnimation.Show ();
myTouchObjectScript.BallForce(hit.transform.gameObject.tag.ToString(), touchY, screenHeight);
}
}
}
}
}

Related

Is there a way to only acces one collider when there are many colliders with the same tag?

I have a script that moves the object you're touching to the position of your finger, it's based on a tag so when I touch an object with the tag all the objects with the same tag move to that position. Is there a way to make only the one I'm touching move?
The Script
{
void FixedUpdate()
{
if (Input.touchCount > 0)
{
RaycastHit2D hitInformation = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position),Camera.main.transform.forward);
if (hitInformation.collider.gameObject.tag == "RocketPrefab")
{
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
touchPosition.z = -4;
transform.position = touchPosition;
Debug.Log(touchPosition);
}
}
}
} ```
You can access the object your Raycast is touching with hitInformation.collider.gameObject.
From the code that I'm seeing, I think this should work:
void FixedUpdate()
{
if (Input.touchCount > 0)
{
RaycastHit2D hitInformation = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position),Camera.main.transform.forward);
if (hitInformation.collider.gameObject.tag == "RocketPrefab")
{
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
touchPosition.z = -4;
hitInformation.collider.gameObject.transform.position = touchPosition;
Debug.Log(touchPosition);
}
}
}
I'm assuming the script is on the parent of all "RocketPrefab" GameObjects and you are then moving them all with the line transform.position = touchPosition;
With that assumption... to get the specific one that the raycast hit you would need to edit the script to move the collider.gameObjct.transformnot just transform
Edited FixedUpdate
void FixedUpdate()
{
if (Input.touchCount > 0)
{
RaycastHit2D hitInformation = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position),Camera.main.transform.forward);
if (hitInformation.collider.gameObject.tag == "RocketPrefab")
{
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);
touchPosition.z = -4;
hitInformation.collider.gameObject.transform.position = touchPosition; // Note this line and how it targets the specific transform
Debug.Log(touchPosition);
}
}
}

Moving objects independently of each other, with the ability to move at the same time in Unity 2D

I have two objects. The point is that I need to move the object up and down (hold and drag), and at the same time I need to move the other object up and down (hold and drag) independently. Something like this:
Example
After searching the Internet, I found a small script, but it only works for one touch at a time, and dragging only one object. Plus, if I touch with second finger the object changes his position to second finger position:
public class Move : MonoBehaviour {
private Vector3 offset;
void OnMouseDown() {
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(-2.527f, Input.mousePosition.y));
}
void OnMouseDrag() {
Vector3 curScreenPoint = new Vector3(-2.527f, Input.mousePosition.y);
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;
transform.position = curPosition;
}
}
I just can’t understand how I can make two objects drag and drop at the same time. I am new to unity and honestly i have problems with controllers
For touch screens I suggest you use Touch instead of mouse events. Touch class supports multiple touches at the same time and some useful information such as Touch.phase (Began, moving, stationary etc). I've written a script which you can attach to multiple objects with tag "Draggable", that makes objects move independently. Drag and drop the other object that should move when you use one finger to field otherObj and it should work. It only works for 2 obj in this version.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
public class PlayerActionHandler : MonoBehaviour
{
private Camera _cam;
public bool beingDragged;
public Vector3 offset;
public Vector3 currPos;
public int fingerIndex;
public GameObject otherObj;
// Start is called before the first frame update
void Start()
{
_cam = Camera.main;
}
// Update is called once per frame
void Update()
{
//ONLY WORKS FOR 2 OBJECTS
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began)
{
var raycast = _cam.ScreenPointToRay(Input.GetTouch(0).position);
RaycastHit hit;
if (Physics.Raycast(raycast, out hit))
{
//use this tag if you want only chosen objects to be draggable
if (hit.transform.CompareTag("Draggable"))
{
if(hit.transform.name == name)
{
//set being dragged and finger index so we can move the object
beingDragged = true;
offset = gameObject.transform.position - _cam.ScreenToWorldPoint(Input.GetTouch(0).position);
offset = new Vector3(offset.x, offset.y, 0);
fingerIndex = 0;
}
}
}
}else if (Input.touchCount == 1 && beingDragged)
{
otherObj.transform.SetParent(transform);
if (Input.GetTouch(fingerIndex).phase == TouchPhase.Moved ){
Vector3 pos = _cam.ScreenToWorldPoint(Input.GetTouch(fingerIndex).position);
currPos = new Vector3(pos.x, pos.y,0) + offset;
transform.position = currPos;
}
}
//ONLY WORKS FOR 2 OBJECTS_END
else if (beingDragged && Input.touchCount > 1)
{
//We tie each finger to an object so the object only moves when tied finger moves
if (Input.GetTouch(fingerIndex).phase == TouchPhase.Moved ){
Vector3 pos = _cam.ScreenToWorldPoint(Input.GetTouch(fingerIndex).position);
currPos = new Vector3(pos.x, pos.y,0) + offset;
transform.position = currPos;
}
}else if (Input.touchCount > 0)
{
for (var i = 0; i < Input.touchCount; i++)
{
//We find the fingers which just touched the screen
if(Input.GetTouch(i).phase == TouchPhase.Began)
{
var raycast = _cam.ScreenPointToRay(Input.GetTouch(i).position);
RaycastHit hit;
if (Physics.Raycast(raycast, out hit))
{
//use this tag if you want only chosen objects to be draggable
if (hit.transform.CompareTag("Draggable"))
{
if(hit.transform.name == name)
{
//set being dragged and finger index so we can move the object
beingDragged = true;
offset = gameObject.transform.position - _cam.ScreenToWorldPoint(Input.GetTouch(i).position);
offset = new Vector3(offset.x, offset.y, 0);
fingerIndex = i;
}
}
}
}
}
}else if (Input.touchCount == 0)
{
//if all fingers are lifted no object is being dragged
beingDragged = false;
}
}
}

iTween.fadeTo() is not fading objects away

I am trying to make an object slowly fade away and then get destroyed. I have been using iTween.fadeTo function to achieve the desired behavior. However, after the assigned time to finish the fadeTo() function, the object gets destroyed without fading away. I don't know what I need to set up to make the object fade away before get destroyed. (The code below is fixed to the desired behavior)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
void horizontalMovement ()
{
mousePosition = Input.mousePosition;
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit)) {
if (hit.collider != null) {
GameObject[] tiles = GameObject.FindGameObjectsWithTag("Floor");
int interations = 0;
foreach (GameObject tile in tiles) {
interations = interations + 1;
float tilePosition = tile.transform.localPosition.x;
float hitPostion = hit.transform.gameObject.transform.localPosition.x;
float minimunValue = tilePosition - hitPostion;
if (minimunValue == 0) {
iTween.FadeTo(tile, iTween.Hash(
"alpha", 1f,
"amount", 0f,
"time", 1f,
"onCompleteTarget", gameObject,
"onComplete", "destroy",
"oncompleteparams", tile)
);
}
}
Debug.Log ("clean objects horizontally");
}
}
Debug.Log ("Horizontal Movement is working" + mousePosition);
}
public void destroy(GameObject anyObject){
Destroy (anyObject);
Debug.Log ("Item will be destroyed");
}
Instead of Destroy() method you could use nameYourObject.SetActive(false);
It will dissapear your object as well.

getting information from sphereCast's hit

I know how to get information from a RayCast but couldn't find anything good on sphereCast.
When I shoot a raycast to an enemy I can detect it's health component and reduce it's health.
It's code:
shootRay.origin = transform.position;
shootRay.direction = transform.forward
if (Physics.Raycast(shootRay, out shootHit, 100f, shootableMask))
{
EnemyHealth enemyHealth = shootHit.collider.GetComponent<EnemyHealth>();
if (enemyHealth != null)
{
enemyHealth.TakeDamage(damagePerShot, shootHit.point);
}
}
Now I want to do a similar thing with SphereCast but instead of one enemy I want to detect all enemys in the hit area and reduce their health.
if (Physics.SphereCast(shootRay, 5f, out shootHit, 100f, shootableMask))
{
// ???
}
According to this (http://answers.unity3d.com/questions/486261/how-can-i-raycast-to-multiple-objects.html) all you need to do is to use RaycastAll:
Example:
void Update() {
RaycastHit[] hits;
hits = Physics.RaycastAll(transform.position, transform.forward, 100.0F);
int i = 0;
while (i < hits.Length) {
RaycastHit hit = hits[i];
Renderer rend = hit.transform.GetComponent<Renderer>();
if (rend) {
rend.material.shader = Shader.Find("Transparent/Diffuse");
rend.material.color.a = 0.3F;
}
i++;
}
}

rigidbody.AddForce affects all game objects with the same script component

on scene I have 3 balls with Ball.cs script attached to each of them. And when I push ball with mouse all balls start moving, but I need that only one that I touch moves.
Here is my FixedUpdate:
void FixedUpdate() {
if(!isMoving) {
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100)) {
if(hit.collider.tag == "Ball") {
startPos = hit.point;
}
}
}
if (startPos != Vector3.zero && Input.GetMouseButtonUp(0)) {
endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 direction = endPos - startPos;
direction.Normalize();
float distance = Vector3.Distance(endPos, startPos);
rigidbody.AddForce(direction * distance * force * Time.deltaTime, ForceMode.Impulse);
isMoving = true;
}
} else {
if(rigidbody.velocity.sqrMagnitude == 0) {
isMoving = false;
startPos = endPos = Vector3.zero;
}
}
}
Like Nick Udell already mentioned, your comparison of the tag is the source of your problem. All three balls are executing the same script at nearly the same time. So if you click on of the balls, all three scripts will cast a ray at your mouse position and check if they hit a ball. Guess what? All of them hit a ball but not the ball they belong to.
You need to check if they are hitting the collider attached to their GameObject
if (hit.collider == collider) {
// do stuff
}

Categories