I try to make a game for android where you have press and hold buttons to move and lift to stop. However, I couldn't make it work on android, because the OnMouseDown and OnMouseUp only works for PC. Is there any way to do it in android? Here is my code:
using UnityEngine;
using System.Collections;
public class buttonRight : MonoBehaviour {
public Rigidbody player;
public float speed;
private bool clicking;
void OnMouseDown()
{
Debug.Log("click");
clicking = true;
Vector3 movement = new Vector3(1.0f, 0.0f, 0.0f);
if (clicking == true)
player.velocity = movement * speed;
}
void OnMouseUp()
{
Debug.Log("stop click");
clicking = false;
Vector3 movement = new Vector3(0.0f, 0.0f, 0.0f);
player.velocity = movement * 0;
}
}
A thousand times question. Well, answer is OnMouseDown and OnMouseUp execute only once and you are trying to use them as OnMouseDown executes per frame.
You can do something like,
Vector3 movement = new Vector3 (1.0f, 0.0f, 0.0f);
bool clicking = false;
void Update ()
{
if (clicking == true)
_rb.velocity = movement * 5;
else
_rb.velocity = movement * 0;
}
void OnMouseDown ()
{
Debug.Log ("click");
clicking = true;
}
void OnMouseUp ()
{
Debug.Log ("stop click");
clicking = false;
}
Related
I'm using Unity 2D for my game and I'm facing a weird problem. I have a GameObject (an image) in my scene with a button attached to it. When the player is out of the screen, the image that works as a GameOver panel appears and in case of enough coins, you can resume the game. Everything works fine but when the image appears and I click on button to resume, the image doesn't disappear while the function for decreasing number of coins still works.
Here is my script in which di() is for die and but() for button:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using CodeStage.AntiCheat.ObscuredTypes;
using CodeStage.AntiCheat.Detectors;
public class UIManager2 : MonoBehaviour {
public static ObscuredInt coin_score = 0;
public Text coin_text;
public Slider slider;
public Slider slider1;
public Slider slider2;
public GameObject bul;
public bool reverse;
public float timer;
public int delay = 1;
public float speed=0.5f;
public GameObject pause;
public AudioSource[] aud=new AudioSource[3];
void Start () {
coin_score = ObscuredPrefs.GetInt ("Score");
StartCoroutine (elapsed ());
slider1.minValue = 0;
slider1.maxValue = 20;
bul = GameObject.FindGameObjectWithTag ("Player").GetComponent<Plane19> ().bullet;
}
void Update () {
timer += Time.deltaTime;
if (timer >= delay && reverse == false) {
timer = 0f;
slider2.value++;
}
if (timer >= delay && reverse == true) {
timer = 0f;
slider2.value -= speed;
}
coin_text.text = coin_score.ToString ();
ObscuredPrefs.SetInt ("Score", coin_score);
if (slider2.value == 10) {
bul.SetActive (false);
reverse = true;
}
if (slider2.value == 0) {
bul.SetActive (true);
reverse = false;
}
}
public void di(){
pause.SetActive(true);
GetComponent<AudioSource>().Pause();
Time.timeScale = 0;
aud[0].Play();
aud[1].Pause();
aud[2].Pause();
}
public void but(){
pause.SetActive(false);
Time.timeScale=1;
aud[0].Pause();
aud[1].UnPause();
aud[2].UnPause();
GetComponent<AudioSource>().UnPause();
UIManager2.coin_score-=2;
}
IEnumerator elapsed () {
yield return new WaitForSeconds (2f);
slider.value++;
StartCoroutine (elapsed ());
}
}
I am new to Unity, and was following the tutorials of roll a ball.
I was to create it for both mobile and desktop and it is working but the only problem I have is that I am unable to create touch keys arrows(left,right,up,down) to control the player on the touch screen devices.
Please check my code below of controlling the player:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed;
public Text countText;
public Texture2D button1; //button 1
public Texture2D button2; //button2
public Texture texture;
private Rigidbody rb;
private int count;
// Use this for initialization
void Start () {
Screen.orientation = ScreenOrientation.LandscapeLeft;
//GUITexture.texture = button1;
rb = GetComponent<Rigidbody> ();
count = 0;
SetCountText ();
}
// Update is called once per frame
void FixedUpdate () {
Screen.orientation = ScreenOrientation.LandscapeLeft;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
if (SystemInfo.deviceType == DeviceType.Desktop) {
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
GetComponent<Rigidbody>().AddForce (movement * speed * Time.deltaTime);
if (Input.GetKey("escape"))
{
Application.Quit();
}
}//END Desktop
else
{
float moveHorizontal = Input.acceleration.x;
float moveVertical = Input.acceleration.y;
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
GetComponent<Rigidbody>().AddForce (movement * speed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
foreach(Touch touch in Input.touches)
{
//Always getting error here
if (GUITexture.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
GUITexture.texture = button2;
transform.Translate(Vector3.right*30*Time.smoothDeltaTime);
}else if(GUITexture.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
GUITexture.texture = button1;
}
}
}
// Building of force vector
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("Pick Up"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Count:" + count.ToString ();
}
}
Your trying to call HitTest directly from GUITexture like a static function but HitTest isn't a static function, you need to create a variable from GUITexture class and then call HitTest function from that object like this:
public GUITexture guiT;
if (guiT.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
guiT.texture = button2;
transform.Translate(Vector3.right*30*Time.smoothDeltaTime);
}
else if(guiT.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
guiT.texture = button1;
}
don't forget to assign guiT variable to something from the Editor.
I'm trying to set the camera position to the position of a body, but when I do this, the body will jump very noticeably. You can see this with the debug renderer but I have a sprite attached in my code. The jump is always in the direction that the sprite is headed. I've got a fixed time step with interpolation, and I update the sprites position to an interpolated value of the current and last position of a box2d body every frame. Then set the camera to the interpolated position.
import java.util.Random;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Input.Orientation;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.JointEdge;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class GameScreen implements Screen {
private static learnGame game;
private static OrthographicCamera camera;
private static FitViewport viewport;
private static Random rand;
private static BitmapFont font;
private static Vector3 touch;
private static double frameTime;
private static double accumulator;
private static float animTime = 0f;
private static float step = 1f / 60f;
private static boolean killBody;
private static Buttons buttons;
public static Player tom;
public static InputMultiplexer multiplexer;
public static Bodies world;
public static boolean paused;
private static Sprite tomSprite = new Sprite(new Texture(Gdx.files.internal("chars/bob.png")));
public GameScreen(learnGame learngame) {
GameScreen.game = learngame;
multiplexer = new InputMultiplexer();
Gdx.input.setInputProcessor(multiplexer);
camera = new OrthographicCamera();
viewport = new FitViewport(40, 22.5f, camera);
buttons = new Buttons(game, multiplexer, viewport); //HUD stuff
world = new Bodies(viewport, multiplexer); //creates a box2d world
tom = new Player(world.box2d, 10, 15, 1f, multiplexer); //creates a body with a CircleShape with a radius of 1. Catches user input to apply forces to the body
Assets.loadSprites();
world.box2d.getBodies(world.bodies);
font = new BitmapFont();
touch = new Vector3();
rand = new Random();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
learnGame.batch.setProjectionMatrix(camera.combined);
frameTime = 0;
if (!paused) {
frameTime = Math.min(Gdx.graphics.getRawDeltaTime(), 0.25);
accumulator += frameTime;
tom.update(); //here I apply forces to the body that I attach a camera to
generalUpdate(delta, touch, camera);
updatePositions(); //get previous positions for interpolation
while (accumulator >= step) {
world.box2d.step(step, 6, 2);
accumulator -= step;
interpolate((float) (accumulator / step));
}
world.box2d.clearForces();
learnGame.batch.begin();
if (tom.getBody().isActive()) {
tomSprite.setSize(tom.getHeight(), tom.getHeight());
tomSprite.setOriginCenter();
tomSprite.setRotation(Assets.tom.angle);//this doesn't work right but not the point.
tomSprite.setPosition(Assets.tom.pos.x, Assets.tom.pos.y);
tomSprite.draw(learnGame.batch);
}
learnGame.batch.end();
cameraUpdate(); //update the camera to the same position as the sprite
} else { //else pause the game
learnGame.batch.begin();
learnGame.batch.draw(Assets.pauset, viewport.getCamera().position.x
- (viewport.getCamera().viewportWidth / 2), viewport.getCamera().position.y
- (viewport.getCamera().viewportHeight / 2), viewport.getWorldWidth(), viewport.getWorldHeight());
learnGame.batch.end();
if (Gdx.input.isKeyJustPressed(Keys.SPACE) || Gdx.input.justTouched()) {
paused = false;
}
}
//destroy fixtures and bodies outside of the world step
for (Fixture fixture : Bodies.fixturesToDestroy) {
if (Bodies.destroyJoint == true) {
world.box2d.destroyJoint(Bodies.joint);
Bodies.joint = null;
Bodies.destroyJoint = false;
}
fixture.getBody().destroyFixture(fixture);
Bodies.fixturesToDestroy.removeValue(fixture, true);
}
for (Body body : Bodies.bodiesToDestroy) {
world.box2d.destroyBody(body);
body.setActive(false);
Bodies.bodiesToDestroy.removeValue(body, true);
}
}
#Override
public void show() {
Assets.firstSound.play();
}
#Override
public void resize(int width, int height) {
viewport.update(width, height, true);
Assets.reloadFont();
}
#Override
public void pause() {
paused = true;
}
#Override
public void resume() {
}
#Override
public void hide() {
paused = true;
}
#Override
public void dispose() {
Bodies.box2d.dispose();
Bodies.debugRenderer.dispose();
Buttons.stage.dispose();
Assets.cFrame.getTexture().dispose();
Assets.firstSound.dispose();
System.out.println("disposed");
}
public void generalUpdate(float delta, Vector3 touch, OrthographicCamera camera) {
if (Gdx.input.isKeyPressed(Keys.PAGE_UP)) {
camera.zoom -= 2f * Gdx.graphics.getDeltaTime();
;
} else if (Gdx.input.isKeyPressed(Keys.PAGE_DOWN)) {
camera.zoom += 2f * Gdx.graphics.getDeltaTime();
}
}
public static void cameraUpdate() {
camera.position.set(Assets.tom.pos, 0);
System.out.println("cam:" + Assets.tom.pos.x);
camera.update();
}
public static void kill() {
world.box2d.dispose();
world.debugRenderer.dispose();
Assets.cFrame.getTexture().dispose();
}
public void updatePositions() {
for (MySprite name : Assets.spriteList) {
name.prevPos = name.body.getTransform().getPosition();
name.prevAngle = name.body.getTransform().getRotation();
}
}
public void interpolate(float alpha) {
for (MySprite name : Assets.spriteList) {
name.pos.x = (name.body.getTransform().getPosition().x) * alpha + name.prevPos.x * (1.0f - alpha);
name.pos.y = (name.body.getTransform().getPosition().y) * alpha + name.prevPos.y * (1.0f - alpha);
name.angle = (name.body.getTransform().getRotation() * alpha + name.prevAngle * (1.0f - alpha));
}
}
}
I have tested my interpolation implementation without the camera moving and it appears to work fine. I've been able to test this on my desktop and on my android. The sprite "jumps" a lot more on my android but it happens on both devices. Not sure where I went wrong here, would really appreciate some input!
It's an old question, I know, but I just solved my Problem today.
I have implemented a fixed Timestep and interpolation, but my body lagged and jittered and jumped like there would be no tomorrow.
Please do following things to your camera Movement:
Use the interpolated Position from the body, NOT the original body position.
Use camera.position.slerp(x, y, z, alpha) to do a smooth movement. (You need to play a bit with the variables.
A really simple Example:
static Vector3 desiredPosition;
static {
desiredPosition = new Vector3(0, 0, 0);
}
public static moveCam(Player player, Camera camera){
desiredPosition.x = player.interpolatedPos.x;
desiredPosition.y = player.interpolatedPos.y;
camera.slerp(desiredPosition, Gdx.graphics.getDeltaTime * 5);
camera.update();
}
and in your render do the following
render(float delta){
moveCam(player, camera);
}
(Instant position setting caused jitter for my moving Object)
I wanted to give up my project, because of this bug. But I managed to do it. I hope it'll help people out there.
€dit: A guess why the jumping body is happening:
The interpolated position is not synchron with the camera (set Position then update world(now interpolated pos is offset with camera), then draw)
But I'm not sure with this.
This is my code to add sprites on Scene.
for (int i = 3; i <= cage.getDirtMeter(); i++) {
Sprite dirtSprite = new Sprite(0, 0, Main.dirtTextureRegion,
mainActivity.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY) {
removeDirt(this);
return true;
}
};
float x = Utility.getRandomXWithinCamera(dirtSprite);
float y = Utility.getRandomYWithinCamera(dirtSprite);
dirtSprite.setPosition(x, y);
this.registerTouchArea(dirtSprite);
attachChild(dirtSprite);
}
and here is my removeDirt method
public void removeDirt(final Sprite sprite) {
synchronized (this) {
if (CoolDown.getSharedInstance().checkValidity()) {
if (isCleanSelected) {
Log.d("detach", "Calling remove dirt");
cage.removeDirt();
mainActivity.runOnUpdateThread(new Runnable() {
#Override
public void run() {
/* Now it is save to remove the entity! */
if (MainMenuScene.this.detachChild(sprite)) {
Log.d("detach", "detached Successfuly!");
}
}
});
updateMetersUI();
}
}
}
}
After removeDirt is called sprite isn't visible on screen but sprites onAreaTouch is still being called even sprites is being deAttached successfully. Any idea how to completely remove sprite from scene. thanks. And I have also tried
sprite.setVisible(false);
sprite.clearEntityModifiers();
sprite.setIgnoreUpdate(true);
sprite.clearUpdateHandlers();
sprite.reset();
sprite.detachSelf();
But after that onAreaTouch is still being called.
You need to Unregister Touch Areas of your Sprite from the scene.
eg
yourScene.unregisterTouchArea(yourSprite);
I have to animate an image as per (x,y) from one point to another point, then that point to another point and so on. I have around 300 points. For that I am using the following code.
/** code starts **/
public class CircleAnimation extends Activity implements OnPreparedListener {
/** Called when the activity is first created. */
ImageView imv1;
int totalAnimTime = 0;
double[][] points = {{258.8505,143.2875,67},
{259.642, 143.3665,120},
{260.429, 142.992,240},
{259.257, 139.3575,180},
......................
......................
{255.1335,146.8135,67},
{255.1395,146.794,67},
{255.0635,146.7785,67},
{254.9045,146.797,1200}
};
int j=0;
double loc[] = new double[2];
double x1 = 0,y1 = 0,x2 = 0,y2 = 0,anim_end=0, xstart=258.8505, ystart=143.2875, xnow, ynow;
protected boolean _active = true;
protected int _animTime = 66;
int k=1;
double xFactor = 1.779167, yFactor = 1.5;
private int displayWidth, displayHeight;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imv1 = (ImageView)findViewById(R.id.imv1);
try{
LaunchInAnimation();
}catch(Exception e){
e.printStackTrace();
}
}
class LocalAnimationListener implements AnimationListener {
public void onAnimationEnd(Animation animation){
imv1.post(mLaunchSecondAnimation);
k = k ++;
}
public void onAnimationRepeat(Animation animation)
{
}
public void onAnimationStart(Animation animation)
{
}
};
private Runnable mLaunchSecondAnimation = new Runnable(){
public void run(){
LaunchInAnimation();
}
};
LocalAnimationListener MyAnimationListener = new LocalAnimationListener();
public void LaunchInAnimation() {
//animation
if(k<points.length) {
if(k==0) {
x1 = xstart;
y1 = ystart;
anim_end=1;
} else {
x1 = points[k-1][0];
y1 = points[k-1][1];
}
x2 = points[k][0];
y2 = points[k][1];
_animTime = (int) (points[k][2]);
TranslateAnimation translateAnimation = new TranslateAnimation((float)x1, (float)x2, (float)y1, (float)y2);
translateAnimation.setDuration(_animTime);
translateAnimation.setFillBefore(true);
translateAnimation.setFillAfter(true);
translateAnimation.setAnimationListener(MyAnimationListener);
imv1.startAnimation(translateAnimation);
totalAnimTime += _animTime;
}
}
}
/** code ends **/
To complete all the animations it should take totalAnimTime, but it is taking less time to complete. Moreover this time is varying from one device to another device. For this, I facing problem to synchronize other event. What is the problem in this code? Is there any other better way to control this type animation.
I was messing with this variance in performance myself, and then I switched to OpenGL to do all my rendering and have since found everything much smoother and simpler once you understand what you're doing.
If you feel OpenGL/SurfaceView is a little too dense for what you're asking for, try using Canvas?
Should be much easier with one of those because they're more stable from device to device. XML animations are simply tricking you into thinking they're animations, their actual X/Y don't ever really change. They have to "flicker" from their original X/Y to the "next step X/Y" right before drawn if I'm correct....