I have a game made with unity, subway surfers like, everything it's done BUT:
On the laptop I can use the arrow keys for left and right to move the player but on the phone I can't, no button, no tilt, no swipe, nothing.
I attached my script here, please help me with some controls, but to be the same value with left and right.
Thank you!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Range(-2, 2)] public float value;
public float Speed;
Rigidbody rigid;
private Transform player;
private Vector3 desiredPosition;
void Start()
{
rigid = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
transform.position = new Vector3(value, transform.position.y, transform.position.z);
rigid.velocity = (Vector3.forward * Time.deltaTime * Speed);
}
private void LateUpdate()
{
if (Input.GetButtonDown("Right"))
{
if (value == 2)
return;
value += 2;
}
if (Input.GetButtonDown("Left"))
{
if (value == -2)
return;
value -= 2;
}
}
}
I would say that you need to find the position of the finger at the start using touch.position. Make sure that the touch is a touch. Then keep finding the position of the touch until it has traveled as far as you want it to. Then, call the function which moves the character. This unity documentation may help you as well with touch input.
https://docs.unity3d.com/ScriptReference/Touch.html
Related
I am a freshman design student and they've asked us to create a game on unity3D without much training on it so needless to say I don't know much except for the super basic stuff. I don't know anything about c# and I've been having an issue making a gameobject teleport. I've spent 6 hours searching for a solution online and the only conclusion I got to was that my object is probably having issues teleporting because of the way I am controlling it - something to do with the controller remembering the last position before the teleport and returning to it. I have no idea how to fix it though.
So this is what my scene looks like: I have a sphere as my character, I move it to this other object that has a collider as trigger which then teleports my sphere to a different point (black object) on the terrain. As soon as my object reaches there, it starts sliding back to the point where the teleport happened. I even tried edit > project settings > physics > auto sync transforms as many suggested that and it worked for them.
This is the code by which I control my player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyPlayer : MonoBehaviour
{
public float speed = 1;
public float spacing = 1;
private Vector3 pos;
// Use this for initialization
void Awake()
{
pos = transform.position;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
pos.x += spacing;
if (Input.GetKeyDown(KeyCode.S))
pos.x -= spacing;
if (Input.GetKeyDown(KeyCode.D))
pos.z -= spacing;
if (Input.GetKeyDown(KeyCode.A))
pos.z += spacing;
transform.position = Vector3.MoveTowards(transform.position, pos, speed * Time.deltaTime);
}
}
and I also have a camera that follows the sphere using this code
using UnityEngine;
using System.Collections;
public class CompleteCameraController : MonoBehaviour {
public GameObject player; //Public variable to store a reference to the player game object
private Vector3 offset; //Private variable to store the offset distance between the player and camera
// Use this for initialization
void Start ()
{
//Calculate and store the offset value by getting the distance between the player's position and camera's position.
offset = transform.position - player.transform.position;
}
// LateUpdate is called after Update each frame
void LateUpdate ()
{
// Set the position of the camera's transform to be the same as the player's, but offset by the calculated offset distance.
transform.position = player.transform.position + offset;
}
}
and I have another code on the camera that makes me be able to look around using my mouse
using UnityEngine;
using System.Collections;
public class FlyCamera : MonoBehaviour
{
/*
Writen by Windexglow 11-13-10. Use it, edit it, steal it I don't care.
Converted to C# 27-02-13 - no credit wanted.
Simple flycam I made, since I couldn't find any others made public.
Made simple to use (drag and drop, done) for regular keyboard layout
wasd : basic movement
shift : Makes camera accelerate
space : Moves camera on X and Z axis only. So camera doesn't gain any height*/
float mainSpeed = 700.0f; //regular speed
float shiftAdd = 950.0f; //multiplied by how long shift is held. Basically running
float maxShift = 2000.0f; //Maximum speed when holdin gshift
float camSens = 0.25f; //How sensitive it with mouse
private Vector3 lastMouse = new Vector3(255, 255, 255); //kind of in the middle of the screen, rather than at the top (play)
private float totalRun = 1.0f;
void Update()
{
lastMouse = Input.mousePosition - lastMouse;
lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0);
lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0);
transform.eulerAngles = lastMouse;
lastMouse = Input.mousePosition;
//Mouse camera angle done.
//Keyboard commands
float f = 0.0f;
Vector3 p = GetBaseInput();
if (Input.GetKey(KeyCode.LeftShift))
{
totalRun += Time.deltaTime;
p = p * totalRun * shiftAdd;
p.x = Mathf.Clamp(p.x, -maxShift, maxShift);
p.y = Mathf.Clamp(p.y, -maxShift, maxShift);
p.z = Mathf.Clamp(p.z, -maxShift, maxShift);
}
else
{
totalRun = Mathf.Clamp(totalRun * 0.5f, 1f, 1000f);
p = p * mainSpeed;
}
p = p * Time.deltaTime;
Vector3 newPosition = transform.position;
if (Input.GetKey(KeyCode.Space))
{ //If player wants to move on X and Z axis only
transform.Translate(p);
newPosition.x = transform.position.x;
newPosition.z = transform.position.z;
transform.position = newPosition;
}
else
{
transform.Translate(p);
}
}
private Vector3 GetBaseInput()
{ //returns the basic values, if it's 0 than it's not active.
Vector3 p_Velocity = new Vector3();
if (Input.GetKey(KeyCode.W))
{
p_Velocity += new Vector3(0, 0, 1);
}
if (Input.GetKey(KeyCode.S))
{
p_Velocity += new Vector3(0, 0, -1);
}
if (Input.GetKey(KeyCode.A))
{
p_Velocity += new Vector3(-1, 0, 0);
}
if (Input.GetKey(KeyCode.D))
{
p_Velocity += new Vector3(1, 0, 0);
}
return p_Velocity;
}
}
Please let me know if there's a specific part of my code that I need to edit to resolve this or alternatively if you have a different code that won't give me this issue, that would make my life so much easier. If I need to edit something or you're sharing a code, please respond with the complete (corrected) code because otherwise I will just be even more confused.
I know this is a super long post and I am sorry but I am really desperate. It's been really hard studying online and basically having to teach myself all of this. This is for a final project so I will really appreciate any help you can throw my way. Thank you for reading and thanks for any help in advance.
EDIT: The teleport code is executing fine because I do teleport to the chosen location, I just end up sliding back to the point which I teleported from.
This is the teleporting code I am using.
using UnityEngine;
using System.Collections;
public class Teleport : MonoBehaviour
{
public GameObject ui;
public GameObject objToTP;
public Transform tpLoc;
void Start()
{
ui.SetActive(false);
}
void OnTriggerStay(Collider other)
{
ui.SetActive(true);
if ((other.gameObject.tag == "Player") && Input.GetKeyDown(KeyCode.E))
{
objToTP.transform.position = tpLoc.transform.position;
}
}
void OnTriggerExit()
{
ui.SetActive(false);
}
}
Ok, so the main reason why your character is drifting back to original position is that the pos variable in the MyPlayer script stays the same after teleporting.
Remedy for that will be changing pos variable from Teleport script after objToTP.transform.position = tpLoc.transform.position;. Something like objToTP.gameobject.GetComponent<MyPlayer>().pos = tpLoc.transform.position;
But make sure that objToTP has component MyPlayer and pos in MyPlayer is public.
Once again: it's a simple way to resolve your problem. In a real project you should create more flexible architecture, but that's a different story.
I believe that you sliding back because you moving player with transform.position = Vector3.MoveTowards in Update().
And you moving it to coordinates that was got from your input
I'm making a unity game based off of TierZoo, and while testing a movement script, i crashed into one of the rigidbody trees for fun... and that made the player prefab stop moving forward, and it started moving in odd directions Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewPlayerController : MonoBehaviour
{
private Rigidbody rb;
public GameObject player;
public float thrust = 1.0f;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.W))
{
rb.AddRelativeForce(player.transform.right * thrust * 2.5f);
}
if (Input.GetKey(KeyCode.A)) { player.transform.Rotate(0, -1, 0); }
if (Input.GetKey(KeyCode.D)) { player.transform.Rotate(0, 1, 0); }
if (Input.GetKey(KeyCode.S))
{
rb.AddRelativeForce(player.transform.right * thrust * -2.5f);
}
}
}
If you can find a way to fix this, let me know.
You could fix the rotation also in Y direction by keeping track of it and setting it hard in FixedUpdate.
In general as said in the comments:
Whenever a Rigidbody is involved you should not
do movements through the transform component
do movements in Update
both breaks the physics engine and you might get strange and unexpected movements or simply no collisions working etc.
Rather do
- go through the Rigidbody component e.g. using MovePosition and MoveRotation
- do these in FixedUpdate
these keeps the physics intact and moves your Rigidbody only e.g. until it collides meanwhile.
Then for the rotation you have framerate-dependent values Rotate(0, -1, 0)! You rather want to use Time.deltaTime in order to get smooth framerate-independent rotation speed - not in 1 degree per frame but rather e.g. 45 degrees per second.
You script could look like
public class NewPlayerController : MonoBehaviour
{
// already reference this via the Inspector
[SerializeField] private Rigidbody rb;
public GameObject player;
public float thrust = 1.0f;
private void Awake()
{
// as fallback get it on runtime
if(!rb) rb = GetComponent<Rigidbody>();
}
bool moveLeft;
bool moveRight;
bool rotateLeft;
bool rotateRight;
private float angle;
void Update()
{
// Get User input here
// (in your case it would be also fine to do it in FixedUpdate.
// What doesn't work in FixedUpdate are mainly the one-time events like GetKeyDown)
moveRight = Input.GetKey(KeyCode.W);
rotateLeft = Input.GetKey(KeyCode.A);
rotateRight = Input.GetKey(KeyCode.D);
moveLeft = Input.GetKey(KeyCode.S);
}
private void FixedUpdate()
{
if(moveRight) rb.AddRelativeForce(rb.rotation * Vector3.right * thrust * 2.5f);
if(moveLeft) rb.AddRelativeForce(rb.rotation * Vector3.right * thrust * -2.5f);
// Now for the rotations keep track of what you rotated already
// and overwrite the rotation with the fix value:
if(rotateLeft)
{
// e.g. for rotating 45°/second
angle -= -45 * Time.deltaTime;
rb.MoveRotation(Quaternion.Euler(0, angle, 0));
}
if(rotateRight)
{
angle += 45 * Time.deltaTime;
rb.MoveRotation(Quaternion.Euler(0, angle, 0));
}
}
}
I want the object to shrink after I touch it in Unity.I want the ball object to shrink slightly after touching it with the mouse. How can I do that? Thanks in advance for your help.
using UnityEngine;
using System.Collections;
public class Point : MonoBehaviour
{
public float speed = 10f;
private Vector3 targetPosition;
private bool isMoving;
public GameObject clickAnimation;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonUp(0))
{
targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
targetPosition.z = transform.position.z;
if (isMoving == false)
{
isMoving = true;
Instantiate(clickAnimation, targetPosition, Quaternion.identity);
}
}
if (isMoving == true)
{
transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
}
if (targetPosition == transform.position)
{
isMoving = false;
Destroy(GameObject.Find("Click Animation(Clone)"));
}
}
}
So you have multiple scenarios to achieve this, dependings on what you need at the end. Let's say you want to shrink any object clicked by the mouse.
You want to raycast everytime you click, and get the gameobject that was hit. In order to do this, you can use the RaycastHit and get the gameobject using RaycastHit.transform.gameObject, you can find the implementation right there and the official Unity documentation here.
After you retrieved your gameobject from the raycast hit, you can shrink it using the setScale transform method. Think that you can use the Vector3 class operator overloading to create the new scale vector.
If you want to shrink the object during the click, you'll have to use Time.deltaTime to "create" the shrink animation.
I stumbled across a problem while working with the book "Unity in Action". At the end of chapter 3 you'd end up with the basics for a simple fps game. It's basically a player (camera attached to it) in a simple and small level which only exists out of a number of cubes forming walls and the floor etc. These cubes all have box collider on them. Now the player is also able to shoot at moving enemies which are also able to shoot. This was done by Raycast/RaycastHit. All this worked perfectly so I wanted to add something that reassembles bullet holes, simply by instantiating a black sphere object on the wall where the fireball (this is the object the enemy and the player shoot) hits it. This works BUT sometimes the fireball object just goes through the wall. In case there is another wall behind it, the fireball object gets destroyed by this second wall and the desired sphere is created on the second wall instead of on the first wall.
I changed the speed in the fireball from 20 to 10 and then back to 20 and at a speed of 10, the success rate is around 19/20, while at a speed of 20 it's around 6/10.
Here is the code of the fireball which is supposed to check whether it hits the player (then health is deducted, that works fine) or hits the enemy (then the enemy falls over, also works fine) or hits the wall in which case the sphere should be created.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fireball : MonoBehaviour {
public float speed = 10.0f;
public int damage = 1;
[SerializeField] private GameObject wallHit;
private GameObject _wallHit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.Translate(0,0, speed * Time.deltaTime);
}
void OnTriggerEnter(Collider other){
RaycastHit hit;
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
ReactiveTarget target = other.GetComponent<ReactiveTarget>();
WallBehavior wall = other.GetComponent<WallBehavior>();
if(player != null){
player.Hurt(damage);
}
if(target != null){
target.ReactToHit();
}
if(wall != null){
if(Physics.Raycast(transform.position, transform.forward, out hit)){
wall.WallWasHit(hit);
}
}
Destroy(this.gameObject);
}
}
As you can see one thing I tried was to give each wall a WallBehavior script, which looks like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallBehavior : MonoBehaviour {
[SerializeField] private GameObject wallHit;
private GameObject _wallHit;
static int count = 0;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void WallWasHit(RaycastHit hit){
count++;
Debug.Log("Wall was hit: " + count);
_wallHit = Instantiate(wallHit) as GameObject;
_wallHit.transform.position = hit.point;
}
}
But none of my attempts to understand why this happens so infrequently was successful so far and I hope someone can help me with this because I feel like might be crucial for my learning before I continue with the book! Thanks in advance. if further information are needed, I am happy to provide them. See the following picture for a better visualization of the issue.
EDIT:
As mentioned in the answers, I replaced the fireball script accordingly but I am not sure how to change the following script likewise. This script is on my camera which is on my player object. In the Update function the Fireball is instantiated and also given a movement, so I guess this causes the problems?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayShooter : MonoBehaviour {
private Camera _camera;
[SerializeField] private GameObject fireballPrefab;
private GameObject _fireball;
void Start () {
_camera = GetComponent<Camera>();
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void OnGUI(){
int size = 12;
float posX = _camera.pixelWidth/2 - size/4;
float posY = _camera.pixelHeight/2 - size/2;
GUI.Label(new Rect(posX, posY, size, size), "X");
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButtonDown(0)){
Vector3 point = new Vector3(_camera.pixelWidth/2, _camera.pixelHeight/2, 0);
_fireball = Instantiate(fireballPrefab) as GameObject;
_fireball.transform.position = transform.TransformPoint(Vector3.forward * 1.5f);
_fireball.transform.rotation = transform.rotation;
Ray ray2 = _camera.ScreenPointToRay(point);
RaycastHit hit;
if(Physics.Raycast(ray2, out hit)){
GameObject hitObject = hit.transform.gameObject;
ReactiveTarget target = hitObject.GetComponent<ReactiveTarget>();
if(target !=null){
target.ReactToHit();
}
}
}
}
}
This is not how to move a Rigidbody Object and moving it like this could cause so many issues including the one mentioned in your question. Objects with Rigidbody should be moved with the Rigidbody component and with the functions like Rigidbody.MovePosition, Rigidbody.AddForce and Rigidbody.velocity not by the transform or transform.Translate.
Also, you should move the Rigidbody Object in the FixedUpdate function instead of the Update function. If you are moving your other Rigidbody Objects by their transform then you must fix them too. The example below replaces transform.Translate with Rigidbody.MovePosition in the Fireball script:
public float speed = 10.0f;
public int damage = 1;
[SerializeField]
private GameObject wallHit;
private GameObject _wallHit;
public Rigidbody rb;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
//Move to towards Z-axis
Vector3 pos = new Vector3(0, 0, 1);
pos = pos.normalized * speed * Time.deltaTime;
rb.MovePosition(rb.transform.position + pos);
}
void OnTriggerEnter(Collider other)
{
RaycastHit hit;
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
ReactiveTarget target = other.GetComponent<ReactiveTarget>();
WallBehavior wall = other.GetComponent<WallBehavior>();
if (player != null)
{
player.Hurt(damage);
}
if (target != null)
{
target.ReactToHit();
}
if (wall != null)
{
if (Physics.Raycast(transform.position, transform.forward, out hit))
{
wall.WallWasHit(hit);
}
}
Destroy(this.gameObject);
}
If you still run into issues, use Rigidbody.velocity instead:
void FixedUpdate()
{
Vector3 pos = Vector3.zero;
pos.z = speed * Time.deltaTime;
rb.velocity = pos;
}
Sometimes, depending on the size of the object and the speed it is moving by, you many need to set its Rigidbody Interpolate from None to Interpolate and Collision Detection to Continuous.
Don't forget to remove the code in the Update function.
EDIT:
I looked at your project and found new problems:
1.You enabled IsTrigger on your "Fireball" GameObject. Please uncheck the IsTrigger on the collider.
2.You just want to shoot a bullet. The force should be added once only not every FixedUpdate. Add the force in the Start function instead of the FixedUpdate function. Use Rigidbody.velocity instead of Rigidbody.MovePosition.
Remove the FixedUpdate function and the code inside it.
This should be your new Start function:
void Start()
{
rb = GetComponent<Rigidbody>();
Vector3 pos = transform.forward * speed * Time.deltaTime;
rb.velocity = pos;
}
I have this these sprites in my game;
player
circle(1)
circle(2)
circle(3)
circle(4)
circle(5)
circle(6)
The circles are spaced out. I have managed to make the player move from circle(1) to circle(2) when the spacebar is pressed using the code below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
private Vector3 player;
public GameObject position1;
public float speed = 30;
void Update()
{
if (Input.GetKeyDown("space"))
player = position1.transform.position;
player.z = transform.position.z;
transform.position = Vector3.MoveTowards(transform.position, player, speed * Time.deltaTime);
}
}
I need the player to 'zap' to the circles one by one each time the spacebar is pressed, so from circle(1) to circle (2) to circle(3) to circle(4) and so on...
I would also need a way of going beyond circle(6) and to carry on, in theory, to infinity.
I am coding in C# and using Unity 5.5
Thank you in advance
If your goal is to have the player move towards a target, and to have the target change every time the space bar is pressed, you'll need to do a few simple things.
public class Movement : MonoBehaviour
{
// You'll need a list of available targets
public List<Transform> Targets;
// The speed to move at
public float Speed = 30;
// A variable to keep track of the current target
private int _currentTargetIndex = 0;
public void Update()
{
// Get the current target
var target = Targets[_currentTargetIndex];
// Move towards it every frame
transform.position = Vector3.MoveTowards(transform.position, target.position, Speed);
// If the space bar was pressed this frame
if(Input.GetKeyDown("space"))
{
// Select the next target
_currentTargetIndex++;
// If we've run out of targets, wrap around to the beginning
if(_currentTargetIndex >= Targets.Count)
{
_currentTargetIndex = 0;
}
}
}
}
this is a code will work fine . First , you need to have a Rigidbody in your player . ,than add this code :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
public GameObject position1;
public GameObject position2;
public GameObject position3;
public GameObject position4;
public GameObject position5;
public GameObject position6;
public int PressedTime;
public float speed = 30;
void Update()
{
if (Input.GetKeyDown("space"))
{
PressedTime += 1;
if (PressedTime == 1)
{
transform.position = Vector3.MoveTowards(transform.position, position1.transform.position, speed);
}
if (PressedTime == 2)
{
transform.position = Vector3.MoveTowards(transform.position, position2.transform.position, speed);
}
if (PressedTime == 3)
{
transform.position = Vector3.MoveTowards(transform.position, position3.transform.position, speed);
}
if (PressedTime == 4)
{
transform.position = Vector3.MoveTowards(transform.position, position4.transform.position, speed);
}
if (PressedTime == 5)
{
transform.position = Vector3.MoveTowards(transform.position, position5.transform.position, speed);
}
if (PressedTime == 6)
{
GetComponent<Rigidbody>().AddForce(position6.transform.position * speed);
}
}
}
}
and set variable position1 to 6 in inspector
if (Input.GetKeyDown("space"))
{
transform.position = Vector3.MoveTowards(transform.position, position1.transform.position, speed);
}
For other circle , you can set variable position2 3 4 5 and so on .
and make 'int PressedTime' , when PressedTime is 6 , turn off the code above and addforce to your gameobject toward the 6th circle .
if my code work , don't forget to accept my answer ! :)