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.
Related
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.
I'm creating a 2D horizontal side-scroller and I have enemies being spawned whose rigidbody component is being used to give them a velocity like so:
using UnityEngine;
using System.Collections;
public class Mover : MonoBehaviour
{
public float speed;
public new Rigidbody2D rigidbody;
public bool random;
void Start()
{
if (random) {
rigidbody.velocity = Random.value * transform.right * speed;
}
else
{
rigidbody.velocity = transform.right * speed;
}
}
}
How can I have these enemies also move up and down constantly on the the Y-axis while they are moving with a velocity on the X-axis? Everything I have tried seems to interfere with the velocity of the objects. I am basically trying to create a simple behavioral pattern so as to make the targets harder for the player to aim at.
Any ideas?
This is just a starting point, but you would have to experiment with different ways to do it to get the behavior you want. Maybe you can try using rigidbody.AddForce too.
If you haven't already, I recommend watching the video tutorials for the 2D platformer.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public class Mover : MonoBehaviour {
public float speed, waveSpeed;
new Rigidbody2D rigidbody;
public bool random;
// Use this for initialization
void Start () {
rigidbody = GetComponent<Rigidbody2D>();
if (random) {
rigidbody.velocity = Random.value * transform.right * speed;
} else {
rigidbody.velocity = transform.right * speed;
}
}
float angle = 0;
// Use this for physics calculations
void FixedUpdate () {
var wave = Mathf.Sin(angle += waveSpeed); // goes from -1 to +1
var p = rigidbody.position;
p.y = wave; // or: yCenter + yHeight * wave
rigidbody.position = p;
}
}
I have found the solution by following the answer given under this link: https://gamedev.stackexchange.com/questions/96878/how-to-animate-objects-with-bobbing-up-and-down-motion-in-unity?newreg=ccb2eaf1b725413ca777a68348637990
Here is my updated code:
public class EnemyMover : MonoBehaviour {
public float speed;
public new Rigidbody2D rigidbody;
public bool random;
float originalY;
public float floatStrength = 1;
void Start()
{
this.originalY = this.transform.position.y;
if (random) {
rigidbody.velocity = Random.value * transform.right * speed;
}else
{
rigidbody.velocity = transform.right * speed;
}
}
void Update()
{
transform.position = new Vector3(transform.position.x,
originalY + ((float)System.Math.Sin(Time.time) * floatStrength),
transform.position.z);
}
}
I mean that when the character is walking or running and getting to the clicked point he change the state in the animator from walk/run to idle so it looks like he walk then stop there is no animation between the walk/run and the start/stop.
I have 3 states in the animator. HumanoidWalk, HumanoidRun, HumanoidIdle.
I need something like fading.
For example if in the line:
_animator.CrossFade("Walk", 0);
I will change the 0 to 1 so when he start "Walk" it will be a bit slowly to walking speed. But in "Idle" if i will change it to 1 it will be something else not fading until he stop.
In other words i want to add fading effects when character start/stop walking/running and also when i click/double click and he switch between Walk and Run. Make some fade effects so it will not switch between the states so fast.
using UnityEngine;
using System.Collections;
public class ClickToMove : MonoBehaviour
{
public int speed = 5; // Determines how quickly object moves towards position
public float rotationSpeed = 5f;
private Vector3 targetPosition;
private Animator _animator;
private Vector3 destination;
private Quaternion targetRotation;
public float clickDelta = 0.35f; // Max between two click to be considered a double click
private bool click = false;
private float clickTime;
void Start()
{
_animator = GetComponent<Animator>();
_animator.CrossFade("Idle", 0);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
if (click && Time.time <= (clickTime + clickDelta))
{
_animator.CrossFade("Run", 0);
click = false;
}
else
{
click = true;
clickTime = Time.time;
}
_animator.CrossFade("Walk", 0);
Plane playerPlane = new Plane(Vector3.up, transform.position);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitdist = 0.0f;
if (playerPlane.Raycast(ray, out hitdist))
{
Vector3 targetPoint = ray.GetPoint(hitdist);
targetPosition = ray.GetPoint(hitdist);
targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
destination = targetPosition;
}
}
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed);
if ((transform.position - destination).magnitude < 0.7f)
{
_animator.CrossFade("Idle", 0);
}
}
}
If you increase your transform duration value a little (like 0.25), then you can get a smooth transition between states. Also uncheck "fixed duration".
I have a 3D object on Unity and what I want is simply move this object as soon as the user presses the screen. The problem is that it needs to accelerate first and then, when it is reaching the pressed position, it starts decelerating until it totally stops on that point.
I need this to work in a way that if the user moves his finger, the object will recalculate if it needs to accelerate/decelerate based on his current condition.
I tried this example but, it only works for acceleration and it also seems a little confusing. So, I was thinking if someone else have a better and simple idea to solve this. Can physics help with this? If so, how?
My code is in C#.
Using unity rigidbody system and simple calculate. This is using mouse position, you can change it to touch.
public class MyDragMove : MonoBehaviour {
public float speedDelta = 1.0f;
public float decelerate = 1.0f;
private bool startDrag;
private Vector3 prePos;
void Update () {
this.rigidbody.drag = decelerate; //Rigidbody system can set drag also. You can use it and remove this line.
if (Input.GetKeyDown (KeyCode.Mouse0)) {
prePos = Input.mousePosition;
startDrag = true;
}
if(Input.GetKeyUp(KeyCode.Mouse0))
startDrag = false;
if(startDrag)
ForceCalculate();
}
void ForceCalculate()
{
Vector3 curPos = Input.mousePosition;
Vector3 dir = curPos - prePos;
float dist = dir.magnitude;
float v = dist / Time.deltaTime;
this.rigidbody.AddForce (dir.normalized * v * Time.deltaTime * speedDelta);
prePos = curPos;
}
}
or just use SmoothDamp toward last position.
public class MyDragMove : MonoBehaviour {
public float speedDelta = 1.0f;
public float maxSpeed = 5.0f;
public Vector3 v;
private Vector3 prePos;
void Update () {
if(Input.GetKey(KeyCode.Mouse0))
prePos = Input.mousePosition;
TowardTarget ();
}
void TowardTarget()
{
Vector3 targetPos = Camera.main.ScreenToWorldPoint (new Vector3(prePos.x, prePos.y, 10f)); //Assume your camera's z is -10 and cube's z is 0
transform.position = Vector3.SmoothDamp (transform.position, targetPos, ref v, speedDelta, maxSpeed);
}
}
I have an object called Ball, and I added keyboard interactivity to it(WASD to move the ball)
I need the camera to stay behind and follow the ball, but I am getting errors.
using UnityEngine;
using System.Collections;
public class ballmain : MonoBehaviour {
public bool isMoving = false;
public string direction;
public float camX;
public float camY;
public float camZ;
// Use this for initialization
void Start () {
Debug.Log("Can this run!!!");
}
// Update is called once per frame
void Update () {
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
camZ = rigidbody.transform.position.z;
camera.transform.position = new Vector3(camX, camY, camZ);
//followed by code that makes ball move
}
}
I get error "Assets/ballmain.cs(18,44): error CS1612: Cannot modify a value type return value of 'UnityEngine.Transform.position'. Consider storing the value in a temporary variable"
Does anyone know the answer? If I comment out the code about the camera the ball can move around.
here you go . a full code.
Simple Following
using UnityEngine;
using System.Collections;
public class Follow: MonoBehaviour {
public Transform target;
public float smooth= 5.0f;
void Update (){
transform.position = Vector3.Lerp (
transform.position, target.position,
Time.deltaTime * smooth);
}
}
Advanced Following
using UnityEngine;
using System.Collections;
public class SmoothFollowScript: MonoBehaviour {
// The target we are following
public Transform target;
// The distance in the x-z plane to the target
public int distance = 10.0;
// the height we want the camera to be above the target
public int height = 10.0;
// How much we
public heightDamping = 2.0;
public rotationDamping = 0.6;
void LateUpdate (){
// Early out if we don't have a target
if (TargetScript.russ == true){
if (!target)
return;
// Calculate the current rotation angles
wantedRotationAngle = target.eulerAngles.y;
wantedHeight = target.position.y + height;
currentRotationAngle = transform.eulerAngles.y;
currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position.y = currentHeight;
// Always look at the target
transform.LookAt (target);
}
}
}
If you just simply want to follow the target object align the position of the camera the way you want it and make the camera the child of the target object and the rest will do
Here're one script I found useful during my game development. I didn't create them so I give credit to wiki.unity3d.com for providing this amazing script.
Smooth Follow:
using UnityEngine;
using System.Collections;
public class SmoothFollow2 : MonoBehaviour {
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
}
More information about my work
Include Standard Mobile Asset to your project. It contains a SmoothFollow2D.js code in its script section. Attach this code with the gameobject and initialize public variables. This will simply do the job for you.
I found this simple and useful unity 2d camera follow script.
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start () {
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate () {
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp( transform.position, targetPos + offset, 0.25f);
}
}
}
source unity2d camera follow script
The -= in these lines:
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
is wrong. The -= will attempt to modify the rigidbody.transform.position. You just want -.
However, as it stands, the camera won't track changes in the target's Z position, nor will it track properly if the camera is rotated. To get the correct position you need (in vectors):-
cam_pos = target_pos - dist_to_target * cam_look_at