Unity - make character walk towards touch/drag position? In 3D space? - c#

Ok, I have a 3D Unity game built for iOS where these controls will be implemented (in a first person shooter manner):
Camera follows just behind character
Keeping finger on screen makes character walk, finger up makes it stop
THIS is the problem: wherever the user has started touching the screen, whatever direction they drag (forward, backwards, left right) the character will walk indefinitely in that direction.
This must have done already but I cant find anything anywhere. I have the camera as a child of the character, so that's taken care of but for char movement all I have is:
void Update()
{
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector3 target = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -10f));
transform.Translate(Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime) - transform.position);
}
Which doesn't work as needed. What can I do here?

You can just try to use any king of UI joysticks (https://assetstore.unity.com/packages/tools/input-management/joystick-pack-107631) for example
And access its parameters something like this:
public class TestMovement : MonoBehaviour
{
public float Speed;
public FloatingJoystick Joystick; //Set in the inspector, prefab from the asset
private void Update()
{
transform.Translate(new Vector2(Joystick.Horizontal, Joystick.Vertical) * Speed * Time.deltaTime);
}
}

Related

How To Make The Camera turn around the player using the mouse only separatly from character movement?

Hi Im not very good at c# but good at unity anyway i was making a game like gta v and i start with making the camera first and i have success with that . second thing i have start making is the movement and for the vertical movement it was good but when came to make the horizontal movement it worked too but the problem is when i move left and right the camera are turning left and right using ("a" button And "d" btton) that's mean when ever i move the player left and right the camera is turning left and right too using these two button But this is not what i want . for butter understanding please whatch this video to see the problem https://youtu.be/5ZPQg8EjIJ0 .
Now here is what i did
1- first i made an empty game object that has two things the player prefab and the camera as the child
Notice: i didnt make the camera a child of the player prefab
2- i made the cameraTurn Script And add it to the main camera
Here is the cameraTurn Script
using UnityEngine;
using System.Collections;
public class cameraTurn : MonoBehaviour {
[SerializeField] private Transform target;    
public float rotSpeed = 1.5f;
private float _rotY;
private Vector3 _offset;
void Start()
{
_rotY = transform.eulerAngles.y;
_offset = target.position - transform.position;    
}
void LateUpdate()
{
float horInput = Input.GetAxis("Horizontal");
if (horInput != 0) {    
_rotY += horInput * rotSpeed;
} else {
_rotY += Input.GetAxis("Mouse X") * rotSpeed * 3;    
}
Quaternion rotation = Quaternion.Euler(0, _rotY, 0);
transform.position = target.position - (rotation * _offset);    
transform.LookAt(target);    
}
}
3- I have made an small sphere and add it to the player prefab as a child and made at the top of the character and call it Mind
And Then i have added the mind as a target for the camera so the camera can look at it when ever it turning
Now if you start the game and move your mouse left and right you can see the camera are looking on the player while it move like gta v and also if you pressed [a] key and [d] key the camera will go around too and this is not what i want because if i keep going and making the movement it will be disaster just like the video you have seen in the top
Hope its all good And if there anything feel free to comment and i will give you more info Thanks,

Unity 2D Sprite rotate toward object

I am making this game in unity. It is a 2d race car game where the player is a racer and has to navigate through the road avoiding crashing into cones or other other cars that are also driving on the road. I've created a path for the other NPC cars that are driving on the road and that part works. Those cars follow the path the way I want them to. But what I want to do now is make the NPC car sprites rotate towards the next path point.
So for example if the vehicle is switching lanes or turning a corner, the car should rotate and point towards the next point in their path. This is the code I have:
public Transform[] waypoints; //array to hold all the waypoints in the sprite's path
[SerializeField]
public float moveSpeed = 2.0f;
public int wayPointIndex = 0;
// Start is called before the first frame update
void Start()
{
transform.position = waypoints[wayPointIndex].transform.position;
}
// Update is called once per frame
void Update()
{
Move();
}
public void Move(){
if(wayPointIndex <= waypoints.Length - 1){
transform.position = Vector3.MoveTowards(transform.position, waypoints[wayPointIndex].transform.position, moveSpeed * Time.deltaTime);
if(transform.position == waypoints[wayPointIndex].transform.position){
wayPointIndex+=1;
}
}
}
This is a bird's eye view game by the way. So the vehicles are seen from the top down.
You could use the transform.rotate method. The method uses an angle input, you could calculate the desired angle geometrically with your current orientation angle and the angle to the next waypoint.

Projectile not shooting direction of my weapon

So my game is sort of like a 3d top down shooter, so I want my gun to shoot wherever the mouse is and it wont go to the mouse unless im shooting down. If you've seen brackyes game called ball wars, im sort of trying to replicate one like that but the projectile is not shooting the right way.
I got my script from blackthornprods ranged combat tutorial (which is for 2d so maybe thats the issue but I dont know how to solve it) :
public float speed;
public float lifeTime;
private void Start()
{
Invoke("DestoryProjectile", lifeTime);
}
private void Update()
{
transform.Translate(transform.up * speed * Time.deltaTime);
}
void DestroyProjectile()
{
Destroy(gameObject);
}
Appreciate anyone to try!
Here is my other script:
Camera mainCam;
public GameObject projectile;
public Transform shotPoint;
private float timeBtwShots;
public float startTimeBtwShots;
void Awake()
{
mainCam = Camera.main;
}
void Update()
{
float objectDepthFromCamera = Vector3.Dot(
transform.position - mainCam.transform.position,
mainCam.transform.forward);
Vector3 cursorWorldPosition = mainCam.ScreenToWorldPoint(Input.mousePosition
+ Vector3.forward * objectDepthFromCamera);
Vector3 localUpNeeded = Vector3.Cross(Vector3.forward,
cursorWorldPosition - transform.position);
transform.rotation = Quaternion.LookRotation(Vector3.forward, localUpNeeded);
if(timeBtwShots <= 0)
{
if (Input.GetMouseButtonDown(0))
{
Instantiate(projectile, shotPoint.position, transform.rotation);
timeBtwShots = startTimeBtwShots;
}
}
else
{
timeBtwShots -= Time.deltaTime;
}
}
Projectile not shooting direction of my weapon. Simple solution -
First instantiate or pool the instance of projectile.
Set rotation of projection from the rotation of weapon & set location to spawn point
Now fire, or whatever strategy you are using
Consider Global rotation, if you need help, tell me, I will edit and give a snippet of code.
This should work. If doesn't post all necessary code, I will give a better solution.
Here is sample github project I created, just for you. I opened Unity nearly after a year. Please check all the versions.
Must check :
firing in facing direction 💋
just instantiate at spawn point
just added some rotation
I think this should give you concept.
Press X for a rantom rotation
Press Space to shoot a projectile :lol:
The white cube shows that it always shoots at a constant direction

Unity: Stop Character walk up hills (Angles between last Position & current Position?!)

i'm currently working on a small game in Unity, and i use c# for my code.
The game is a small role playing game, where you control a character like you do in games like world of warcraft or dragon age.
You run around on small maps, with hills around the map. Currently, you can walk up the hills at some places and i want to stop that.
so i thought i write a code where i get the last position of my character and the current position, than i get the angle between them and if the angle is to high, i would force the player to go back (or disable moving forward).
this is what i got for the code so far:
Vector3 lastPos; // last Position
Vector3 curPos; // current Position
float slopeAngle; // The angle between curPos and lastPos
void Start()
{
curPos = transform.position;
}
void FixedUpdate()
{
lastPos = curPos;
curPos = transform.position;
slopeAngle = Vector3.Angle(lastPos, curPos);
}
unfortunately, slopeAngle is mostly between 0 and 0.04. it doesn't matter if i run up a steep mountain or just a flat hill.
any ideas?! (if there is a better solution, than getting the angle between two points, i am very interested!! ) :)
Thanks for your help!
You could try using a Raycast from your character to check if there's a slope high enough to halt your movement.
float maxSlopeAngle;
Transform raycastOrigin;
void FixedUpdate()
{
RaycastHit hit;
Vector3 direction = Quaternion.Euler(-MaxSlopeAngle, 0, 0) * transform.forward;
if (Physics.Raycast(raycastOrigin.position, direction, out hit, 1f))
{
Debug.Log("Slope ahead!");
}
}
Obviously, you'd want to figure out the right maxDistance for the raycast so you won't stop too soon.
Also, you can use the following script to help you figure out the right angle:
[ExecuteInEditMode]
public class SlopeAngleHelper : MonoBehaviour {
public float MaxSlopeAngle;
public Transform RayOrigin;
void Update ()
{
Vector3 direction = Quaternion.Euler(-MaxSlopeAngle, 0, 0) * transform.forward;
Debug.DrawRay(RayOrigin.position, transform.forward, Color.black, 0.01f, false);
Debug.DrawRay(RayOrigin.position, direction, Color.red, 0.01f, false);
}
}
Just put it on your character object and it will "visualize" the raycast in scene view.

Unity3D - Make character moving forward nicely on a seesaw in a 2.5D runner game

What I want to do is to make a kind of 2.5D runner game in Unity, which the character's all three rotation axises are frozen and the position on Z axis is also frozen. I don't know how to make the character moving forward nicely on the seesaw. (I create the seesaw by using HingeJoint.)
I create a struct to detect the CapsuleCollider status by using Physics.Raycast() function and that works fine.
private struct ColliderStatus
{
public bool headed; //colliding up
public bool footed; //colliding down
public bool onPlane; //colliding down && the obstacle colliding does not have slope angle
public bool lefted; //colliding left
public bool righted; //colliding right
public bool inAir; //not colliding anything
}
I've tried these ways:
Add force on Rigidbody to move forward
//To move character rigidbody move forward automatically in runner game
//when the speed is lower than the minimum speed and it's on plane or in air.
if (rigidbody.velocity.x < minForwardSpeed && (colliderStatus.onPlane || colliderStatus.inAir))
{
rigidbody.AddForce(20f * Vector3.right);
}
//Add gravity to player
Vector3 gravityForce = new Vector3(0f, -gravityOnPlayer, 0f);
rigidbody.AddForce(gravityForce);
It doesn't work well because the character continue going up when it's on the seesaw though the seesaw starts to tilt. And there will be a velocity loss when the character fall to ground from a higher plane or after jumping and what it looks like is that the character will stunned for a little moment on the landing point and then begin to accelerate.
Use transform.Translate() to move forward && change the way of adding gravity
//Use transform.Translate() to move forward
//I recognize that by this way, there will be no velocity loss
//when the character falling down to the ground at the landing point
//If I don't use this condition, my character will stuck on the
//right vertical wall
if (!colliderStatus.righted)
{
transform.Translate(new Vector2(minForwardSpeed, 0f) * Time.deltaTime);
}
I don't know why I can't write like this since it will cause the velocity doesn't react correctly:
//Use transform.Translate() to move forward
if (!colliderStatus.righted && rigidbody.velocity.x < minForwardSpeed)
{
transform.Translate(new Vector2(minForwardSpeed, 0f) * Time.deltaTime);
}
To change the way of adding gravity, I use a function SlopeAngleVector() to calculate the slope vector the character is running on.
private Vector3 SlopeAngleVector()
{
Vector3 nextStepPositon = new Vector3(transform.position.x + 0.01f, transform.position.y, 0f);
Ray nextPosRay = new Ray(nextStepPositon, Vector3.down);
Ray nowPosRay = new Ray(transform.position, Vector3.down);
RaycastHit nextPosHit;
RaycastHit nowPosHit;
Vector3 slopeAngle = Vector3.zero;
Physics.Raycast(nowPosRay, out nowPosHit, 5f, obstaclesLayerMask);
if (Physics.Raycast(nextPosRay, out nextPosHit, 5f, obstaclesLayerMask))
{
slopeAngle = new Vector3(nextPosHit.point.x - nowPosHit.point.x, nextPosHit.point.y - nowPosHit.point.y, 0f).normalized;
}
return slopeAngle;
}
Then I add the gravity by calculate the gravity projection on the slope vector:
private void AddGravity()
{
Vector3 gravityForce = new Vector3(0f, -gravityOnPlayer, 0f);
//my character could be collided by the long vertical wall(colliderStatus.righted)
//so I set the condition as "!colliderStatus.footed"
//otherwise, I would use "colliderStatus.inAir"
if (!colliderStatus.footed)
{
gravityForce = new Vector3(0f, -gravityOnPlayer, 0f);
}
else
{
gravityForce = Vector3.Project(Vector3.down * gravityOnPlayer, SlopeAngleVector());
}
rigidbody.AddForce(gravityForce);
}
Now my character can slide down from the seesaw but it will keep going backwards. And it cannot make it through when on the low slope angle seesaw.
How to make a good behavior script for the runner on seesaw?
I'd suggest looking at some of the Unity standard asset character controllers, I believe they take slopes into account for their character movement. It may give you some ideas.
I'd also recommend modifying the way your code calculates the angle of the slope. The raycast hit will give you back a surface normal, you should then be able to use the Vector3.Cross to figure out the angle of the slope.
It'll be something like: Vector3.Cross(normal, (vector that points away from screen)).
You may need to tweak it to get it working correctly but this can give you the slope angle in one raycast. It may also eliminate potential issues of your move to position being just below the see saw.
As a general tip, try not to mix transform and rigidbody stuff together, if you want to move the rigidbody, move the rigidbody directly, not indirectly through the transform.

Categories

Resources