How to make enemies turn and move towards player when near? Unity3D - c#

I am trying to make my enemy object turn and start moving towards my player object when the player comes within a certain vicinity.
For the turning I have been testing the transform.LookAt() function although it isn't returning the desired results as when the player is too close to the enemy object the enemy starts to tilt backwards and I only want my enemy to be able to rotate along the y axis, thanks in advance.
using UnityEngine;
using System.Collections;
public class EnemyController : MonoBehaviour {
public Transform visionPoint;
private PlayerController player;
public Transform Player;
public float visionAngle = 30f;
public float visionDistance = 10f;
public float moveSpeed = 2f;
public float chaseDistance = 3f;
private Vector3? lastKnownPlayerPosition;
// Use this for initialization
void Start () {
player = GameObject.FindObjectOfType<PlayerController> ();
}
// Update is called once per frame
void Update () {
// Not giving the desired results
transform.LookAt(Player);
}
void FixedUpdate () {
}
void Look () {
Vector3 deltaToPlayer = player.transform.position - visionPoint.position;
Vector3 directionToPlayer = deltaToPlayer.normalized;
float dot = Vector3.Dot (transform.forward, directionToPlayer);
if (dot < 0) {
return;
}
float distanceToPlayer = directionToPlayer.magnitude;
if (distanceToPlayer > visionDistance)
{
return;
}
float angle = Vector3.Angle (transform.forward, directionToPlayer);
if(angle > visionAngle)
{
return;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, directionToPlayer, out hit, visionDistance))
{
if (hit.collider.gameObject == player.gameObject)
{
lastKnownPlayerPosition = player.transform.position;
}
}
}
}

change the look at target:
void Update () {
Vector3 lookAt = Player.position;
lookAt.y = transform.position.y;
transform.LookAt(lookAt);
}
this way the look at target will be on the same height as your object.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyMovement : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 4;
int MaxDist = 10;
int MinDist = 5;
void Update()
{
transform.LookAt(Player);
if (Vector3.Distance(transform.position, Player.position) >= MinDist)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, Player.position) <= MaxDist)
{
// Put what do you want to happen here
}
}
}
}

Related

Why does the client sees himself falling through the ground?

Recently I tried making a multiplayer game and I have some problems. After I click "Play" in the menu and I get placed in the multiplayer scene, I see myself falling through the ground, and when I check the "Scene" tab in unity my character is standing where it should be and responds to my movements (as a player, all I can see is the infinite nothing around me but I can still look around, move, etc). When another player connects, he is bugged into the ground (and I can see the shadow from the other player that is hosting and plays directly from unity) and I can't move at all.
Code :
So in the main menu scene, I have this :
NetworkController script :
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NetworkController : MonoBehaviourPunCallbacks
{
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster () {
Debug.Log("coonnected to " + PhotonNetwork.CloudRegion + " server !");
}
void Update()
{
}
}
QuickStartLobbyController script:
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StartLobbyController : MonoBehaviourPunCallbacks
{
[SerializeField] GameObject quickStartButton;
[SerializeField] float roomSize;
public override void OnConnectedToMaster () {
PhotonNetwork.AutomaticallySyncScene = true;
quickStartButton.SetActive(true);
}
public void QuickStart () {
quickStartButton.SetActive(false);
PhotonNetwork.JoinRandomRoom();
Debug.Log("Quick Start!");
}
public override void OnJoinRandomFailed (short returnCode, string message) {
Debug.Log("Failed to join a room");
CreateRoom();
}
public void CreateRoom () {
Debug.Log("creating room");
int randomRoomNumber = Random.Range(0, 10000);
RoomOptions roomOps = new RoomOptions() { IsVisible = true, IsOpen = true, MaxPlayers = (byte)
roomSize };
PhotonNetwork.CreateRoom("Room" + randomRoomNumber, roomOps);
Debug.Log(randomRoomNumber);
}
public override void OnCreateRoomFailed (short returnCode, string message) {
Debug.Log("failed to create a room");
CreateRoom();
}
}
QuickStartRoomController script :
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoomController : MonoBehaviourPunCallbacks
{
[SerializeField] int multiplayerSceneIndex;
public override void OnEnable () {
PhotonNetwork.AddCallbackTarget(this);
}
public override void OnDisable () {
PhotonNetwork.RemoveCallbackTarget(this);
}
public override void OnJoinedRoom () {
Debug.Log("joined room");
StartGame();
}
private void StartGame () {
if ( PhotonNetwork.IsMasterClient ) {
Debug.Log("Starting game");
PhotonNetwork.LoadLevel(multiplayerSceneIndex);
}
}
}
And now, the multiplayer scene where players should see each other:
The player has those :
The script inside GameSetup:
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class GameSetupController : MonoBehaviour
{
void Start()
{
CreatePlayer();
}
private void CreatePlayer () {
Debug.Log("Creating Player");
PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "player"), Vector3.zero,
Quaternion.identity);
}
}
EDIT: so here you can see exactly how it looks like. When I play from the editor's window I can move around even if I can't see it, but with the client, I cannot do basically anything in-game. I think it might be a problem with the GameSetup code or with the part that syncs all the players with the server
EDIT2: posted the playerController script :
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour, IPunObservable {
[SerializeField] Transform camera;
[SerializeField] float sens = 3.5f;
[SerializeField] float walkSpeed = 6.0f;
[SerializeField] [Range(0.0f, 0.5f)] float smooth = 0.3f;
[SerializeField] [Range(0.0f, 0.5f)] float smoothMouse = 0.3f;
[SerializeField] float gravity = -13.0f;
[SerializeField] float slopeForce = 6;
[SerializeField] float slopeForceRayLenght = 1.5f;
[SerializeField] float runSpeed = 10;
[SerializeField] float runBuildUp = 4;
[SerializeField] float jumpForce = 10;
[SerializeField] KeyCode jumpk;
[SerializeField] KeyCode runk;
[SerializeField] bool cursorLock = true;
public Rigidbody rb;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask grndMask;
public bool isGrounded;
float cameraPitch = 0.0f;
float velocityY = 0.0f;
float speed;
Vector2 currentDir = Vector2.zero;
Vector2 currentDirVelocity = Vector2.zero;
Vector2 currentMouseDelta = Vector2.zero;
Vector2 currentMouseDeltaVelocity = Vector2.zero;
CharacterController controller;
PhotonView photonView;
private void Awake () {
photonView = GetComponent<PhotonView>();
photonView.ObservedComponents.Add(this);
if ( !photonView.IsMine ) {
enabled = false;
}
}
void Start () {
speed = walkSpeed;
controller = GetComponent<CharacterController>();
if ( cursorLock ) {
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
// Update is called once per frame
void Update () {
UpdateMouseLook();
UpdateMovement();
Jump();
}
void UpdateMouseLook () {
Vector2 mouseDelta = new Vector2(Input.GetAxis("Mouse
X"),Input.GetAxis("Mouse Y"));
currentMouseDelta = Vector2.SmoothDamp(currentMouseDelta, mouseDelta,ref
currentMouseDeltaVelocity, smoothMouse);
cameraPitch -= currentMouseDelta.y * sens;
cameraPitch = Mathf.Clamp(cameraPitch, -90.0f, 90.0f);
camera.localEulerAngles = Vector3.right * cameraPitch;
transform.Rotate(Vector3.up * currentMouseDelta.x * sens);
}
void SetSpeed () {
if ( Input.GetKey(runk) ) {
speed = Mathf.Lerp(speed, runSpeed, Time.deltaTime * runBuildUp);
} else {
speed = Mathf.Lerp(speed, walkSpeed, Time.deltaTime * runBuildUp);
}
}
void Jump () {
isGrounded = Physics.CheckSphere(groundCheck.position,
groundDistance,grndMask);
if ( isGrounded && Input.GetKeyDown(jumpk) ) {
Debug.Log("jumping");
velocityY = Mathf.Sqrt(jumpForce * -2f * gravity);
controller.Move(Vector3.up * velocityY * Time.deltaTime);
}
}
public bool OnSlope () {
RaycastHit hit;
if ( Physics.Raycast(transform.position, Vector3.down, out hit,
controller.height / 2 * slopeForceRayLenght) ) {
if ( hit.normal != Vector3.up ) {
return true;
}
}
return false;
}
void UpdateMovement () {
Vector2 inputDir = new Vector2(Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical"));
inputDir.Normalize();
currentDir = Vector2.SmoothDamp(currentDir, inputDir, ref
currentDirVelocity, smooth);
if ( controller.isGrounded ) {
velocityY = 0.0f;
}
velocityY += gravity * Time.deltaTime;
Vector3 velocity = (transform.forward * currentDir.y + transform.right *
currentDir.x) * speed + Vector3.up * velocityY;
controller.Move(velocity * Time.deltaTime);
if ( (inputDir.x != 0 || inputDir.y != 0) && OnSlope() ) {
controller.Move(Vector3.down * controller.height / 2 * slopeForce *
Time.deltaTime);
}
SetSpeed();
}
void IPunObservable.OnPhotonSerializeView (PhotonStream stream,
PhotonMessageInfo info) {
if ( stream.IsWriting ) {
// We own this player: send the others our data
stream.SendNext(transform.position); //position of the character
stream.SendNext(transform.rotation); //rotation of the character
} else {
// Network player, receive data
Vector3 syncPosition = (Vector3) stream.ReceiveNext();
Quaternion syncRotation = (Quaternion) stream.ReceiveNext();
}
}
}
EDIT3: I found out something! When I enter the game from the master, I still need to drag myself up a bit in the editor and I will stop falling and I can play the game, but when the 2nd player connects, My camera is set to his (in all this time I can move my character and see this through the 2nd player's camera), and when he leaves all go back to normal on the master player. However, with the 2nd player, I can't move and I get an error that says:5. Btw the 2nd player is the session from the standalone (the built game) and the first player is a session from the unity editor

I'm trying to lerp forward the player a fixed distance but it only works once. How do I allow the player to be moved more than once?

Please check the code. Once the player moves the fixed distance once, he doesn't move again even when the space input is given.
How Do I make it such that I can keep moving the player after the player has been moved once?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovementPC : MonoBehaviour
{
[Header ("Move Settings")]
private Vector3 StartingPosition, EndingPosition;
public float moveDistance = 30f;
public float LerpTime = 1f;
private float CurrentLerpTime = 0;
public bool movePressed = false;
private void Start()
{
StartingPosition = transform.position;
EndingPosition = transform.position + Vector3.forward * moveDistance;
}
void Update()
{
if (Input.GetKeyDown("space"))
{
movePressed = true;
Debug.Log("dash pressed");
}
if (movePressed == true)
{
CurrentLerpTime += Time.unscaledDeltaTime;
if (CurrentLerpTime >= LerpTime)
{
CurrentLerpTime = LerpTime;
}
float LerpPercentage = CurrentLerpTime / LerpTime;
transform.position = Vector3.Lerp(StartingPosition, EndingPosition, LerpPercentage);
}
}
Any Help would be appreciated. Thanks for your time.
The issue is you are not resetting the variables that control the start/end positions of the movement. The Start() method is called when the object is added to the level, or Play is pressed and that is currently the only method that resets those values. Therefore if you want those values reset you need to determine when the movement has finished, something like:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovementPC : MonoBehaviour
{
[Header ("Move Settings")]
private Vector3 StartingPosition, EndingPosition;
public float moveDistance = 30f;
public float LerpTime = 1f;
private float CurrentLerpTime = 0;
private void Start()
{
ResetPositions();
}
void Update()
{
if (Input.GetKeyDown("space"))
{
CurrentLerpTime += Time.unscaledDeltaTime;
if (CurrentLerpTime >= LerpTime)
{
ResetPositions();
return;
}
float LerpPercentage = CurrentLerpTime / LerpTime;
transform.position = Vector3.Lerp(StartingPosition, EndingPosition, LerpPercentage);
}
}
void ResetPositions()
{
StartingPosition = transform.position;
EndingPosition = transform.position + Vector3.forward * moveDistance;
CurrentLerpTime = 0;
}

unity projectile spawns but doesn't pick up velocity?

This is my code does anyone know or can anyone spot why my projectile remains stationary once it's spawned in? the projectile is the prefab shell thanks for your help in advance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankBehaviour : MonoBehaviour
{
public GameObject shellPrefab;
public Transform fireTransform;
private bool isFired = false;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
float x = Input.GetAxis("Horizontal");
float y = Input.GetAxis("Vertical");
transform.position += transform.forward * y;
transform.Rotate(0, x, 0);
if (Input.GetKeyUp(KeyCode.Space) && !isFired)
{
Debug.Log("fire!");
Fire();
}
}
void Fire()
{
//isFired = true;
GameObject shellInstance = Instantiate(shellPrefab,
fireTransform.position,
fireTransform.rotation) as GameObject;
if (shellInstance)
{
shellInstance.tag = "Shell";
Rigidbody shellRB = shellInstance.GetComponent<Rigidbody>();
shellRB.velocity = 15.0f * fireTransform.forward;
Debug.Log("velocity");
}
}
}
It is also generally discouraged to set the velocity of a rigidbody, but you can use the Rigidbody.AddForce() method to add force to a rigidbody. When you just want add force at the start, you can set the force mode in the function to impulse, like this rb.AddForce(Vector3.forward, ForceMode2D.Impulse);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankBehaviour : MonoBehaviour
{
public GameObject shellPrefab;
public Transform fireTransform;
private bool isFired = false;
public float bulletSpeed;
void Update()
{
float x = Input.GetAxis("Horizontal");
float y = Input.GetAxis("Vertical");
transform.position += transform.forward * y;
transform.Rotate(0, x, 0);
if (Input.GetKeyUp(KeyCode.Space) && !isFired)
{
Debug.Log("fire!");
Fire();
}
}
void Fire()
{
//isFired = true;
GameObject shellInstance = Instantiate(shellPrefab, fireTransform.position, fireTransform.rotation) as GameObject;
if (shellInstance)
{
shellInstance.tag = "Shell";
Rigidbody shellRB = shellInstance.GetComponent<Rigidbody>();
shellRB.AddForce(15f * transform.forward, ForceMode.Impulse);
Debug.Log("velocity");
}
}
}
Hope this helps!

Unity how to detect if a specific Game Object is near you

I'm creating a test game because I'm getting ready to create my first game but I want to make sure I get all the simple mechanics down that my first game will require. One of the mechanics that will be included in the game is picking up items if they are a certain distance to you. Sometimes there might be multiple of the same object in the game, I figured the code would work for all coins however that is just not the case. The Debug.Log() only works on one specific coin, how do I make it so it will fire no matter what coin I'm near?
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour {
//Player Variables
public float moveSpeed;
public float jumpHeight;
public float raycastDistanceGround;
public Text moneyText;
private bool isGrounded;
private Rigidbody _rgb;
private GameObject player;
private GameObject[] coin;
private float distanceToCollectCoin;
private float distanceToCoin;
void Start () {
moveSpeed = 7f;
jumpHeight = 9f;
raycastDistanceGround = 0.5f;
isGrounded = true;
_rgb = GetComponent<Rigidbody>();
player = GameObject.FindGameObjectWithTag("Player");
coin = GameObject.FindGameObjectsWithTag("Coin");
distanceToCollectCoin = 2f;
Cursor.lockState = CursorLockMode.Locked;
}
void FixedUpdate () {
IsGrounding();
Move();
Jump();
SetMoneyText();
NearCoin();
}
//Player Moving Mechanics
void Move() {
var moveHorizontal = Input.GetAxis("Horizontal") * moveSpeed * Time.fixedDeltaTime;
var moveVertical = Input.GetAxis("Vertical") * moveSpeed * Time.fixedDeltaTime;
transform.Translate(moveHorizontal, 0f, moveVertical);
if (Input.GetKeyDown(KeyCode.Escape)) {
Cursor.lockState = CursorLockMode.None;
}
}
//Player Jump Mechanics
void Jump() {
var jump = new Vector3(0f, _rgb.position.y, 0f);
if (Input.GetKey(KeyCode.Space) && isGrounded == true) {
for (float i = 0; i <= jumpHeight; i++) {
jump.y += i;
_rgb.AddForce(jump);
}
}
}
void IsGrounding() {
if (Physics.Raycast(transform.position, Vector3.down, raycastDistanceGround)) {
isGrounded = true;
} else {
isGrounded = false;
}
}
void SetMoneyText() {
moneyText.text = ("Money: " + EconomyController.Money);
}
void NearCoin() {
for (int i = 0; i < coin.Length; i++) {
distanceToCoin = Vector3.Distance(coin[i].transform.position, player.transform.position);
}
if (distanceToCoin < distanceToCollectCoin) {
Debug.Log("Near Coin");
}
}
}
Looks like you just bracketed some stuff wrong. You need to move your if-statement into the for-loop. Right now it's only checking the distance for the last coin in the array.
void NearCoin()
{
for (int i = 0; i < coin.Length; i++)
{
distanceToCoin = Vector3.Distance(coin[i].transform.position, player.transform.position);
if (distanceToCoin < distanceToCollectCoin)
Debug.Log("Near Coin");
}
}

how to shoot in the mouse pointer angle?

I have a player which is shooting with bullets to the enemy,the bullets are moving towards the right,in a correct angle,but my bullet is not pointing towards that angle,the bullets is unable to change its angle.,how to change it?,it should not only move in that angle but also point towards it,currently i am transforming it to right of the screen.,the enemy are spawning from the right.here is my code for movement and transformation,any help thanx,
this is the code for direction,and for the shooting rate
using UnityEngine;
using System.Collections;
public class WeaponScript : MonoBehaviour
{
public Transform shotPrefab;
public float shootingRate = 0.25f;
private float shootCooldown;
void Start()
{
shootCooldown = 0f;
}
void Update()
{
if (shootCooldown > 0)
{
shootCooldown -= Time.deltaTime;
}
}
public void Attack(bool isEnemy)
{
if (CanAttack)
{
shootCooldown = shootingRate;
// Create a new shot
var shotTransform = Instantiate(shotPrefab) as Transform;
// Assign position
shotTransform.position = transform.position;
// The is enemy property
ShotScript shot = shotTransform.gameObject.GetComponent<ShotScript>();
if (shot != null)
{
shot.isEnemyShot = isEnemy;
}
// Make the weapon shot always towards it
MoveScript move = shotTransform.gameObject.GetComponent<MoveScript>();
if (move != null)
{
move.direction = this.transform.right;
}
}
}
public bool CanAttack
{
get
{
return shootCooldown <= 0f;
}
}
}
this is the code for movement
using UnityEngine;
using System.Collections;
public class MoveScript : MonoBehaviour {
public Vector2 speed = new Vector2(10,10);
public Vector2 direction = new Vector2(1,0);
void Update () {
Vector3 movement = new Vector3 (speed.x * direction.x, speed.y * direction.y, 0);
movement *= Time.deltaTime;
transform.Translate(movement);
}
}
Using transform.LookAt(transform.position + direction) will immediately point your object in the specified direction.

Categories