I've a problem when I use unity3D with C# to achieve Click To Move.
It means the character move to where my mouse clicked.
But when my character move to destination,it will span itself.
I think it's perhaps wrong in this line
"controller.SimpleMove (transform.forwardspeed);"
when I click to position like(20.5,10.1) with decimal point or some number I can't present in "transform.forwardspeed" ,cause my character can never achieve to this position but keep trying to. So my character span and span.....
It's my guess right?
If true ,how can I fix it?
This is my Script for ClickToMove
using UnityEngine;
using System.Collections;
public class ClickToMove : MonoBehaviour {
public float speed;
public CharacterController controller;
private Vector3 position;
public int arrive =1;
void Start ()
{
}
void Update ()
{
if (Input.GetMouseButton (0))
{
//Locate where we click
locatePosition();
}
MoveToPos ();
//Move to where we click
}
void locatePosition()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, 1000))
{
position = new Vector3(hit.point.x,hit.point.y,hit.point.z);
Debug.Log(position);
}
}
void MoveToPos()
{ if (Vector3.Distance (transform.position, position) > 1)
{
Quaternion newRotation = Quaternion.LookRotation (position - transform.position);
newRotation.x = 0f;
newRotation.z = 0f;
transform.rotation = Quaternion.Slerp (transform.rotation, newRotation, Time.deltaTime * 10);
controller.SimpleMove (transform.forward*speed);
}
}
}
Related
Record of the problem
https://youtu.be/BpzHQkVQz5A
Explaining my problem
I'm programming a mobile game using Unity3D Engine. For my player movement, I'm using NavMeshAgent because it's for me the easiest and most efficient way to do it. But when I hit the play button and ask my player to move, the movements are jerky and it's not pleasant to see at all.
Do you have any idea to fix this problem ?!
Thank you in advance for your answers ! ^^
My code
This is my code :
Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Player : MonoBehaviour
{
NavMeshAgent agent;
Touch touch;
RaycastHit hit;
Ray ray;
// START FUNCTION
private void Start()
{
agent = GetComponent<NavMeshAgent>();
}
// UPDATE FUNCTION
private void Update()
{
// TOUCH DETECTION
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
// A FINGER TOUCHED THE SCREEN
if (touch.phase == TouchPhase.Began)
{
// RETURN X, Y AND Z WORLD POS OF THE TOUCH SCREEN POS
ray = Camera.main.ScreenPointToRay(touch.position);
if (Physics.Raycast(ray, out hit))
{
if (hit.collider != null)
{
// MOVING PLAYER TO THE HIT POS
Vector3 hitVec = new Vector3(hit.point.x, hit.point.y + (GetComponent<Collider>().bounds.size.y / 2), hit.point.z);
agent.SetDestination(hitVec);
}
}
}
}
// SAME CODE USING MOUSE BUTTON
#if UNITY_EDITOR
if (Input.GetMouseButton(0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
if (hit.collider != null)
{
Vector3 hitVec = new Vector3(hit.point.x, hit.point.y + (GetComponent<Collider>().bounds.size.y / 2), hit.point.z);
agent.SetDestination(hitVec);
}
}
}
#endif
}
}
CameraFollow.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// BRACKEYS CAMERA FOLLOW SCRIPT WITHOUT THE LOOKAT METHODE
public class CameraFollow : MonoBehaviour
{
public Transform target;
public float smoothSpeed = 0.2f;
public Vector3 offset;
void FixedUpdate()
{
Vector3 desiredPosition = target.position + offset;
Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
transform.position = smoothedPosition;
}
}
The problem isn't the navmesh controller but the camera follow script.
One thing you could try is to move the camera position using only the desiredPosition or use Vector3.SmoothDamp:
private Vector3 velocity;
void LateUpdate(){
...
Vector3 desiredPosition = target.position + offset;
Vector3 smoothedPosition = Vector3.SmoothDamp(transform.position, desiredPosition, ref velocity, smoothSpeed);
transform.position = smoothedPosition;
}
Also this is explained in a pinned comment on the Brackeys video
I'm making an enemy in my 2D Unity game, and I was trying to flip the sprite when it faces the opposite direction, the thing is, the sprite would only flip when the player was very close to the enemy. This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMovement : MonoBehaviour
{
public float moveSpeed;
private PlayerMovement player;
public float playerRange;
public LayerMask playerLayer;
public bool playerinRange;
private bool Right = false;
private void Start()
{
player = FindObjectOfType<PlayerMovement>();
}
private void Update()
{
playerinRange = Physics2D.OverlapCircle(transform.position, playerRange, playerLayer);
if (playerinRange)
{
transform.position = Vector3.MoveTowards(transform.position, player.transform.position, moveSpeed * Time.deltaTime);
}
Flip();
}
private void OnDrawGizmosSelected()
{
Gizmos.DrawSphere(transform.position, playerRange);
}
private void Flip()
{
if (transform.position.x > 0 && !Right || transform.position.x < 0 && Right)
{
Right = !Right;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
}
Looking at your code, what's happening is that the direction the enemy is facing is dependent of the position of the enemy in the world (since you are using the x component of transform.position). If your enemy x position is positive, the Right boolean will be true, otherwise it will be false (also the 0 case isn't accounted for).
Since the only thing that can move the enemy in this code snippet is the Vector3.MoveToward when the player is in range, I suspect what's happening is that as your player gets close, the enemy moves and the x position value goes from negative to positive (or the opposite), flipping the sprite.
Now, linking the sprite direction to the enemy's position isn't something you want to do. Instead, you want the enemy to face the direction it is moving toward. This can be done by having a velocity parameter that you use to move your enemy and which will tell you in which direction he is moving (and at which speed) for instance. If you want to keep the move toward, then you need to figure out in which direction it is making you move and flip the sprite accordingly. Here is a code example base on your code:
private void Update()
{
playerinRange = Physics2D.OverlapCircle(transform.position, playerRange, playerLayer);
if (playerinRange)
{
transform.position = Vector3.MoveTowards(transform.position, player.transform.position, moveSpeed * Time.deltaTime);
Flip(player.transform.position.x - transform.position.x);
}
}
private void Flip(float direction)
{
Right = (direction >= 0);
Vector3 theScale = transform.localScale;
theScale.x = Mathf.Abs(theScale.x) * Mathf.Sign(direction);
transform.localScale = theScale;
}
I have a problem that I can not solve. I have an object, and I want when I click somewhere near him to move with some force. something like the picture below.
I'd even want some idea!!!
Help!!!
public float speed;
public GameObject player;
Vector3 target;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
var mouseClick = Input.mousePosition;
mouseClick.z = player.transform.position.z - Camera.main.transform.position.z;
target = Camera.main.ScreenToWorldPoint(mouseClick);
var distanceToTarget = Vector3.Distance(player.transform.position, target);
if (distanceToTarget > 2)
{
target.z = 0;
player.GetComponent<Rigidbody2D>().AddForce(target * speed);
}
else
print("travelling COMPLETE");
}
}
Using the code you provided in your answer...
public float speed;
public GameObject player;
Vector3 directionVector;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
// Input.mousePosition is already in pixel coordinates so the z should already be 0.
Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
// Now that the mouse is a world position lets set his z to the same as the player
mouseWorldPosition.z = player.transform.position.z;
// Gives us a direction from the mouse to the player. So think of it as Player <- Mouse remove the < and you have the equation
directionVector = player.transform.position - mouseWorldPosition;
}
else
{
directionVector = Vector3.zero;
}
}
// Physics based movement should be done in FixedUpdate
private void FixedUpdate()
{
player.GetComponent<Rigidbody2D>().AddForce(directionVector.normalized * speed);
}
I'm new to Unity and have been following a tutorial on how to make a Captain Blaster 2D game, however I want to convert it to Android, I want to make the player controllable by dragging him across the screen with one finger and don't understand what's wrong with my code, anything helps, thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ShipControl : MonoBehaviour {
public float playerSpeed = 10f;
public GameControl gameController;
public GameObject bulletPrefab;
public float reloadTime = 1f;
private float elapsedTime = 0;
void Update()
{
elapsedTime += Time.deltaTime;
if (Input.touchCount >= 1)
{
foreach (Touch touch in Input.touches)
{
Ray ray = Camera.main.ScreenPointToRay (touch.position);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, 100)) {
}
}
if (elapsedTime > reloadTime)
{
Vector3 spawnPos = transform.position;
spawnPos += new Vector3 (0, 1.2f, 0);
Instantiate (bulletPrefab, spawnPos, Quaternion.identity);
elapsedTime = 0f;
}
}
}
void OnTriggerEnter2D(Collider2D other)
{
gameController.PlayerDied ();
}
}
What I would do is add a bool called "dragging" and after you check if Raycast hit anything you also check if hit object is the player GameObject.
If it is then as long as user is not releasing the touch - make player's rigidbody move towards the touch position (so if there are any obstacles it simply doesn't move right through them).
Code would probably look like this (you should also add some timer to check if player released touch and set dragging bool to false):
public float playerSpeed = 10f;
public GameControl gameController;
public GameObject bulletPrefab;
public float reloadTime = 1f;
private float elapsedTime = 0;
private bool dragging = false;
void Update()
{
if (Input.touchCount >= 1)
{
foreach (Touch touch in Input.touches)
{
Ray ray = Camera.main.ScreenPointToRay (touch.position);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, 100))
{
if(hit.collider.tag == "Player") // check if hit collider has Player tag
{
dragging = true;
}
}
if(dragging)
{
//First rotate the player towards the touch (should do some checks if it's not too close so it doesn't glitch out)
Vector3 _dir = Camera.main.ScreenToWorldPoint(touch.position) - transform.position;
_dir.Normalize();
float _rotZ = Mathf.Atan2(_dir.y, _dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, _rotZ - 90);
//Move towards the touch
transform.GetComponent<Rigidbody>().AddRelativeForce(direction.normalized * playerSpeed, ForceMode.Force);
}
}
}
}
I am creating a 2D side-scroller video game in Unity using c#. I have created the script that makes the player face the direction that the arrow key that was pressed was pointing to (when the right arrow is pressed, the player faces right. When the left arrow is pressed, the player faces left).
However, I cannot figure out how to make the harpoon that the player shoots point in the direction the player is facing. I have found many questions on Stack Overflow asking questions like this, but none of their answers worked for me.
Can anyone please tell me how to make the harpoon the player shoots face the direction the player is facing? Thanks in advance!
Here is my code that I use-
PLAYER SCRIPT
using UnityEngine;
using System.Collections;
public class playerMove : MonoBehaviour {
// All Variables
public float speed = 10;
private Rigidbody2D rigidBody2D;
private GameObject harpoon_00001;
private bool facingRight = true;
void Awake () {
rigidBody2D = GetComponent<Rigidbody2D>();
harpoon_00001 = GameObject.Find("harpoon_00001");
}
void Update () {
if (Input.GetKeyDown(KeyCode.LeftArrow) && !facingRight) {
Flip();
}
if (Input.GetKeyDown(KeyCode.RightArrow) && facingRight) {
Flip();
}
}
void Flip () {
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void FixedUpdate () {
float xMove = Input.GetAxis("Horizontal");
float yMove = Input.GetAxis("Vertical");
float xSpeed = xMove * speed;
float ySpeed = yMove * speed;
Vector2 newVelocity = new Vector2(xSpeed, ySpeed);
rigidBody2D.velocity = newVelocity;
if (Input.GetKeyDown("space")) {
GetComponent<AudioSource>().Play();
Instantiate(harpoon_00001,transform.position,transform.rotation);
}
}
}
HARPOON SCRIPT
using UnityEngine;
using System.Collections;
public class harpoonScript : MonoBehaviour {
// Public variable
public int speed = 6;
private Rigidbody2D r2d;
// Function called once when the bullet is created
void Start () {
// Get the rigidbody component
r2d = GetComponent<Rigidbody2D>();
// Make the bullet move upward
float ySpeed = 0;
float xSpeed = -8;
Vector2 newVelocity = new Vector2(xSpeed, ySpeed);
r2d.velocity = newVelocity;
}
void Update () {
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
float xSpeed = -8;
}
if (Input.GetKeyDown(KeyCode.RightArrow)) {
float xSpeed = 8;
}
}
void OnTriggerEnter2D(Collider2D other) //hero hits side of enemy
{
Destroy(other.gameObject.GetComponent<Collider2D>()); //Remove collider to avoid audio replaying
other.gameObject.GetComponent<Renderer>().enabled = false; //Make object invisible
Destroy(other.gameObject, 0.626f); //Destroy object when audio is done playing, destroying it before will cause the audio to stop
}
}
You already defining a variable facingRight to know the direction of the the player. You can use that knowledge to control the harpoon.
For example:
// this line creates a new object, which has harpoonScript attached to it.
// In unity editor, you drag and drop this prefab(harpoon_00001) into right place.
// transform.position is used for the starting point of the fire. You can also add +-some_vector3 for better placement
// Quaternion.identity means no rotation.
harpoonScript harpoon = Instantiate(harpoon_00001,transform.position, Quaternion.identity) as harpoonScript;
// Assuming harpoon prefab already facing to right
if (!facingRight) {
// Maybe, not required
harpoon.transform.eulerAngles = new Vector3(0f, 0f, 180f); // Face backward
Vector3 theScale = harpoon.transform.localScale;
theScale.y *= -1;
harpoon.transform.localScale = theScale; // Flip on y axis
}