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 ! :)
Related
So i was trying 3rd character movement in unity an got stuck in here. The player animation is moving in loop but player is moving ahead of camera and than coming back, its doing it every cycle.
Let me provide char_control code and video link.
video link - https://drive.google.com/file/d/15VEIcOqy7yhQfACT4Pjxh-BZoVsrYdFS/view?usp=sharing
code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class char_control : MonoBehaviour
{
public GameObject Player;
//variable - type of variable
public bool isRunning;
public float horizontal_move;
public float vertical_move;
// Update is called once per frame
void Update()
{
if (Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
{
Player.GetComponent<Animation>().Play("Running");
horizontal_move = Input.GetAxis("Horizontal") * Time.deltaTime * 100;
vertical_move = Input.GetAxis("Vertical") * Time.deltaTime * 1;
isRunning = true;
transform.Rotate(0, horizontal_move, 0);
transform.Translate(0, 0, vertical_move);
}
else
{
Player.GetComponent<Animation>().Play("Idle");
isRunning = false;
}
}
}
You should use Animator and Animator Controller for your purpose. To fix your problem you could probably disable root motion in your animation (Bake Into Pose on Root Transform Position (XZ), setting up Mask should work too) but still you will end up using Animator Controller so better do that asap
Have you checked that your "Running" animation has both "Loop Time" and "Loop Pose" checked. I know that the pose option is the one which makes my character act the way you described.
Use scripting to control character movement and movement animations:
[System.Serializable]
public class Anim//Game control animation
{
public AnimationClip idle;
public AnimationClip runForward;
public AnimationClip runBackward;
public AnimationClip runRight;
public AnimationClip runleft;
}
public class playermove : MonoBehaviour {
public float h = 0.0f;
public float v = 0.0f;
//assign the variable,
private Transform tr;
//move speed variable
public float movespeed = 10.0f;
//Rotate can use the Rotate function,
public float rotSpeed = 100.0f;
//The animation class variable to display to the inspector
public Anim anim;
//To access the variables of the following 3d model animation component objects
public Animation _animation;
// Use this for initialization
void Start () {
//Assign the Tr component to the initial part of the script
tr = GetComponent<Transform>();
// Find the anim component that is subordinate to itself and assign it to a variable.
_animation = GetComponentInChildren<Animation>();
_animation.clip = anim.idle;
_animation.Play();
}
// Update is called once per frame
void Update() {
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
Debug.Log("H=" + h.ToString());
Debug.Log("V="+ v.ToString());
//Calculate the moving direction vector of left, right, front and rear.
Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h);
//translate (movement direction *time.deltatime*movespeed, space.self)
tr.Translate(moveDir.normalized *Time.deltaTime*movespeed , Space.Self);
//vector3.up axis as the benchmark, rotate at rotspeed speed
tr.Rotate(Vector3.up * Time.deltaTime * rotSpeed * Input.GetAxis("Mouse X"));
if (v >= 0.1f)
{
//forward animation
_animation.CrossFade(anim.runForward.name, 0.3f);
}
else if (v <= -0.1f)
{
//back animation
_animation.CrossFade(anim.runBackward.name, 0.3f);
}
else if (h >= 0.1f)
{
//right animation
_animation.CrossFade(anim.runRight.name, 0.3f);
}
else if (h <= -0.1f)
{
//left animation
_animation.CrossFade(anim.runleft.name, 0.3f);
}
else
{
_animation.CrossFade(anim.idle.name, 0.3f);
}
//Based on the keyboard input value, execute the animation to be operated
}
}
hope it helps you.
In my game I want to have one of my enemies move towards the player however they don't do that for some reason. The enemy is supposed to look at the player and when the player enters the range they should start moving towards him. My problem is that they aren't doing anything. They just stand there. Also they don't even fall when they have a rigidbody. It currently has an Animator, box collider, and a capsule collider.
Edit: I forgot to add this but the script also triggers the animations
Edit #2: Also I know that it isn't because the movement is in the if statement
(Sorry if it is bad I am a programmer noob)
This is the script responsible for the players movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Mar_Tracker : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 3.0f;
public float InRadius = 250.0f;
public float AttackRange = 11.0f;
public float rocketRange = 50.0f;
private Animator anim;
private Coroutine RocketLouch = null;
public GameObject Rocket;
public GameObject Explosion;
public SphereCollider sphereCollider;
private void Start()
{
anim = GetComponent<Animator>();
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
sphereCollider.enabled = false;
}
void Update()
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player); // Makes it so that the enemy looks at player
float dstSqr = (Player.position - transform.position).sqrMagnitude;
bool inRadius = (dstSqr <= InRadius * InRadius);
bool inAttackRange = (dstSqr <= AttackRange * AttackRange);
bool inRocketRange = (dstSqr <= rocketRange * rocketRange);
anim.SetBool("inArea", inRadius);
anim.SetBool("Attacking", inAttackRange);
if (inRadius)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime; // (movement)
}
if (inRocketRange)
{
if (RocketLouch == null)
{
RocketLouch = StartCoroutine(RocketLaunch());
}
}
}
IEnumerator RocketLaunch()
{
anim.SetBool("Rocket", true);
yield return new WaitForSeconds(0.15f);
sphereCollider.enabled = true;
Explosion.SetActive(true);
yield return new WaitForSeconds(1.0f);
anim.SetBool("Rocket", false);
Destroy(Rocket);
}
}
Your using math that may be a tad to complicated for what you want to achieve and I think the issue is happening there.
Lets simplify it
Transform Player;
float InRadius;
float AttackRange;
float rocketRange;
void Start()
{
// Set it at the start to optimize performance
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
}
// Use fixed Update for moving things around
// Better performance
void FixedUpdate()
{
HandlePlayerDetection() ;
}
void HandlePlayerDetection()
{
transform.LookAt(Player); // Makes it so that the enemy looks at player
// Find the distance between the player and the transform
var distance = Vector3.Distance(transform.position, player.position);
// Do the boolean calculations
bool inRadius = distance <= InRadius;
bool inAttackRange = distance <= AttackRange;
bool inRocketRange = distance <= rocketRange;
// Lets use inbuilt functions to movement
if (inRadius)
{
transform.position = Vector3.MoveTowards(transform.position, Player.position, MoveSpeed * Time.deltaTime);
}
// Rocket code
if (inRocketRange)
{
FireRocket();
}
}
void FireRocket()
{
if (RocketLouch == null)
{
RocketLouch = StartCoroutine(RocketLaunch());
}
}
Now if you really want your enemy to walk properly I would recommend watching a tutorial on Nav Meshes. It is super easy to use and will allow the enemy to walk around objects and do propper path finding.
So i made a little side scroller that uses a prefab to spawn bullets.
My problem is that it only shoots to one side... the Right.
I need it to fire to the left as well. I've already made a variable to see if the player is looking to the right or left.
I've tried to put the Speed to -20 and i've tried to rotate it 180 degrees on it's Z axis. I tested if the bullet script even picked up the change from the player movement script and it does.
Player Movement script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public GameObject bullet;
private Rigidbody2D myRigidbody;
private float speed = 15;
private bool facingRight;
private bool ground = false;
private float jump = 23;
// Start is called before the first frame update
void Start()
{
facingRight = true;
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
Movement(horizontal);
Flip(horizontal);
if (Input.GetKey("w"))
{
if (ground)
{
GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, jump);
}
}
if(facingRight == false)
{
bullet.GetComponent<bullet>().left = true;
}
if (facingRight == true)
{
bullet.GetComponent<bullet>().left = false;
}
}
void OnTriggerEnter2D()
{
ground = true;
}
void OnTriggerExit2D()
{
ground = false;
}
private void Movement(float horizontal)
{
myRigidbody.velocity = new Vector2(horizontal * speed,myRigidbody.velocity.y);
}
private void Flip(float horizontal)
{
if (horizontal > 0 && !facingRight || horizontal < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
}
Weapon script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class weapon : MonoBehaviour
{
// Start is called before the first frame update
public bool right;
public Transform firepointR;
public GameObject bulletPrefab;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown("space"))
{
Debug.Log("Oh well");
Shoot();
}
}
void Shoot()
{
Instantiate(bulletPrefab, firepointR.position, firepointR.rotation);
}
}
bullet script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bullet : MonoBehaviour
{
public bool left;
public float speed = 20;
public Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb.velocity = transform.right * speed;
}
// Update is called once per frame
void FixedUpdate()
{
Debug.Log(speed);
if (left == false)
{
transform.Rotate(0, 0, 180);
}
}
}
As i previously said i need my bullet (prefab) to go the opposite direction but whatever i do right now it will always go right.
Expanding on my comment:
Did you try reversing the velocity?
rb.velocity = -(transform.right * speed);
Note: There are instances when using a negative float wont return the opposite of the positive result. However, in this example, it will work just fine.
I imagine this will work also (and is probably the correct way of doing it):
rb.velocity = transform.left * speed;
I'm replicating project from this site below:
http://blog.lessmilk.com/unity-spaceshooter-1/
http://blog.lessmilk.com/unity-spaceshooter-2/
But, my bullet does not move forward when the spacebar is pressed. Below are my scripts:
spaceshipScript:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spaceshipScript : MonoBehaviour {
public GameObject bullet;
// Use this for initialization
void Start () {
}
void Update() {
// Get the rigidbody component
//var r2d = GetComponent("Rigidbody2D");
float speed = 10.0f;
// Move the spaceship when an arrow key is pressed
if (Input.GetKey (KeyCode.RightArrow))
transform.position += Vector3.right * speed * Time.deltaTime;
else if (Input.GetKey (KeyCode.LeftArrow))
transform.position += Vector3.left * speed * Time.deltaTime;
//BULLET
//When spacebar is pressed
if (Input.GetKeyDown(KeyCode.Space)) {
Instantiate(bullet, transform.position, Quaternion.identity);
}
}
}
bulletScript:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bulletScript : MonoBehaviour {
public int speed = 8;
// Use this for initialization
void Start () {
Input.GetKey (KeyCode.UpArrow);
transform.position += Vector3.right * speed * Time.deltaTime;
}
void OnBecomeInvisible() {
Destroy (gameObject);
}
// Update is called once per frame
void Update () {
}
}
As they are telling you in the comments, you are mixing two different approaches. If you want to modify the position of the bullet using Time.deltaTime you need to move that line to Update()
However if you want to follow the approach of the tutorial, but instead of shooting the bullet from bottom to top, you want to shoot from left to right, you should just change the axis (And dont forget to add a rigid body to the bullet)
// Public variable
public var speed : int = 6;
// Function called once when the bullet is created
function Start () {
// Get the rigidbody component
var r2d = GetComponent("Rigidbody2D");
// Make the bullet move upward
r2d.velocity.x = speed;
}
// Function called when the object goes out of the screen
function OnBecameInvisible() {
// Destroy the bullet
Destroy(gameObject);
}
So basicy i need my character to go up when space or mousebutton are pressed. I added rigbody 2d and box colider 2d to my gameobject (player). The problem is when I hit space or mousebuttonit only jump not constantly moving up.
Here is my code:
using UnityEngine;
using System.Collections;
public class PixelMovement : MonoBehaviour {
Vector3 velocity = Vector3.zero;
public Vector3 PressVelocity;
public float maxSpeed = 5f;
public float fowardSpeed = 1f;
public float jumpForce;
bool didPress = false;
// Use this for initialization
void Start () {
}
//Do Graphic & Input updates
void Update()
{
if (Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
{
didPress = true;
}
}
//Do physics engine updates here
void FixedUpdate()
{
velocity.x = fowardSpeed;
if (didPress == true)
{
didPress = false;
velocity += PressVelocity * Time.deltaTime *jumpForce;
}
velocity = Vector3.ClampMagnitude(velocity, maxSpeed);
transform.position += velocity * Time.deltaTime;
}
}
Ok this works for me. Thanks everyone for help :)
using UnityEngine;
using System.Collections;
public class PixelMovement : MonoBehaviour {
public float playerSpeed;
public Vector3 gravity;
public float maxSpeed = 5f;
Vector3 velocity = Vector3.zero;
public float fowardSpeed = 1f;
bool didPress = false;
void Update()
{
if (Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
{
didPress = true;
}
else
{
didPress = false;
}
}
void FixedUpdate()
{
velocity.x = fowardSpeed;
transform.position += velocity * Time.deltaTime;
if (didPress == true)
{
float amntToMove1 = playerSpeed * Time.deltaTime;
transform.Translate(Vector3.up * amntToMove1);
}
velocity = Vector3.ClampMagnitude(velocity, maxSpeed);
transform.position += velocity * Time.deltaTime;
}
}
If you are using gravity and RigitBody2D's mass. I recomend you use the RigitBody2D.Addforce() method to jump your caracter, because if you just change the caracter position, the gravity will turn down him to the ground inmediately
This code creates the effect of a "rocketman" that takes off when the user keeps the spacebar pressed:
using UnityEngine;
using System.Collections;
public class jumpAntigravity : MonoBehaviour {
Vector2 upForce;
void Start () {
//Up force set to double of gravity
upForce = new Vector2(0, 9.8f*2);
}
void Update () {
if (Input.GetKey(KeyCode.Space))
{
print("Spacebar is down");
GetComponent<Rigidbody2D>().AddForce(upForce);
}
}
}
if (Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0))
{
didPress = true;
}
else
{
didPress = false;
}
and remove didPress = false; from FixedUpdate() function
EDIT: Ok, wait, I just noticed you update transform.position in FixedUpdate() which is not really a good idea. When you do so you basically teleport your object from one position to another ignoring all kinds of physics (which probably is the reason you are using FixedUpdate()). With your script colliding with other objects will give you weird results. Find a tutorial on using RigidBodies to do proper physics-aware movement, or just move all your code to Update() because right now you might have some frames where your object doesn't move and other frames where it moves twice the distance. This will happen because FixedUpdate() may get executed any number of times (including 0) in a single frame, depending on a setup. FixedUpdate runs firmly 50 times per second by default, while Update runs roughly 60 times per second (on mobile 30) by default. And lastly, in FixedUpdate never use Time.deltaTime, use Time.fixedDeltaTime:
Time.deltaTime is equal to roughly 1 / 60th of a second (1 frame duration)
Time.fixedDeltaTime is roughly 1 / 50th of a second (1 physics update duration)
FixedUpdate can be called multiple times per frame in succession. This is based on the physics settings for your project. You can edit this to add more or less accuracy to your physics.
Update is called only 1 time a frame.
So you want to avoid doing logic in the FixedUpdate. If you want to move a rigid body use MovePosition.
From the Unity docs: If Rigidbody interpolation is enabled on the Rigidbody, calling Rigidbody.MovePosition results in a smooth transition between the two positions in any intermediate frames rendered. This should be used if you want to continuously move a rigidbody in each FixedUpdate.