Find nearest waypoint to target in unity 3d - unity3d

I'm developing game like Hitman Go , and I need to find which waypoints are closest to my target(specific waypoint ) when enemy has alerted by rock or sound and etc.
I set some point for enemy and My enemy patrolling between waypoints ( 8 -> 6 -> 1-> 2-> 3-> 4-> 5 ) then reveres his path.
so, when I throw rock in waypoint number 18, I need to move enemy to this waypoint, but with closest way. imaging enemy can be any this waypoint when he get aleret ( 8,6,1,2,3,4,5 points).
Note 1: The distance between two points is same.
Note2: My game is in 3d not 2d.
I use this code to move my enemy step by step ( turn base ).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaypointController : MonoBehaviour
{
public List<Transform> waypoints = new List<Transform>();
private Transform targetWaypoint;
private int targetWaypointIndex = 0;
private float minDistance = 0.1f;
private int lastWaypointIndex;
public bool reversePath;
// what easetype to use for iTweening
public iTween.EaseType easeType = iTween.EaseType.easeInOutExpo;
// how fast we move
public float moveSpeed = 1.5f;
// time to rotate to face destination
public float rotateTime = 0.5f;
// delay to use before any call to iTween
public float iTweenDelay = 0f;
// Use this for initialization
void Start()
{
lastWaypointIndex = waypoints.Count - 1;
targetWaypoint = waypoints[targetWaypointIndex];
}
public void EnemyTurn()
{
float distance = Vector3.Distance(transform.position, targetWaypoint.position);
CheckDistanceToWaypoint(distance);
// move toward the destinationPos using the easeType and moveSpeed variables
iTween.MoveTo(gameObject, iTween.Hash(
"x", targetWaypoint.position.x,
"y", targetWaypoint.position.y,
"z", targetWaypoint.position.z,
"delay", iTweenDelay,
"easetype", easeType,
"speed", moveSpeed
));
}
void CheckDistanceToWaypoint(float currentDistance)
{
if (currentDistance <= minDistance)
{
targetWaypointIndex++;
UpdateTargetWaypoint();
}
}
void UpdateTargetWaypoint()
{
if (targetWaypointIndex > lastWaypointIndex)
{
if (reversePath)
{
waypoints.Reverse();
}
targetWaypointIndex = 1;
}
targetWaypoint = waypoints[targetWaypointIndex];
}
}

Since you asked in the comments for a non-A* solution & I was bored :)
Naive DFS pathfinder with very simple pruning.
Brute force and very wasteful both memory & CPU wise.
For a game similar to Hitman Go / Lara Croft Go - I would use this code and not a navmesh / A*.
For a RTS / FPS or any AI intensive games, I would definitely not use this solution.
public class GridPathfinder
{
// Not thread safe
private int? _currentShortestPath;
/// <summary>
/// Finds shortest path from cell A to B
/// </summary>
/// <returns>Shortest found path; null if found no path.</returns>
public IList<Node> GetShortestPath(Node a, Node b)
{
_currentShortestPath = null;
return GetShortestPathInternal(a, b, new List<Node>());
}
private IList<Node> GetShortestPathInternal(Node #from, Node to, List<Node> currentPath)
{
// Sanity
if (currentPath.Contains(from))
{
return null;
}
// Prune
if (_currentShortestPath.HasValue && currentPath.Count + 1 >= _currentShortestPath)
{
return null;
}
currentPath.Add(from);
if (from == to)
{
return currentPath;
}
// Check neighbors recursively
IList<Node> foundShortestPath = null;
foreach (var connectedCell in from.ConnectedCells)
{
var cellPath = GetShortestPathInternal(connectedCell, to, new List<Node>(currentPath));
if (cellPath == null || foundShortestPath != null && cellPath.Count >= foundShortestPath.Count)
{
continue;
}
foundShortestPath = cellPath;
}
// Update shortest path for future pruning
if (foundShortestPath != null && (!_currentShortestPath.HasValue || _currentShortestPath > foundShortestPath.Count))
{
_currentShortestPath = foundShortestPath.Count;
}
return foundShortestPath;
}
}
public class Node
{
private readonly HashSet<Node> _connectedCells = new HashSet<Node>();
public IEnumerable<Node> ConnectedCells => _connectedCells;
/// <summary>
/// Add a connection
/// </summary>
/// <param name="toAdd">Node to add</param>
/// <param name="isTwoWay">Should add a connection from target node to this node</param>
public void AddConnection(Node toAdd, bool isTwoWay=true)
{
if (toAdd == null || toAdd == this)
{
throw new Exception("Invalid connection attempted");
}
// Attempt to add
if (!_connectedCells.Add(toAdd))
{
return;
}
if (!isTwoWay) return;
toAdd.AddConnection(this);
}
}

Related

Unity: spawning enemies works but they are not visible

I'm busy with creating a school project where I need to integrate wave spawners.
For now, I used this video as an example and implemented it in my project.https://www.youtube.com/watch?v=q0SBfDFn2Bs
Everything is spawning fine and I also get my debug logs. The main problem is: I can't see my enemies. (not John Cena guys hahah, in that case it would be logic ;) )
I'm new to Unity and I like the interface and workflow but I have a lot to learn. I hope someone can help me out! :)
Source WaveSpawner.cs:
using UnityEngine;
using System.Collections;
public class WaveSpawner : MonoBehaviour
{
public enum SpawnState { SPAWNING, WAITING, COUNTING };
[System.Serializable]
public class Wave
{
public string name;
public Transform enemy;
public int count;
public float rate;
}
public Wave[] waves;
private int nextWave = 0;
public int NextWave
{
get { return nextWave + 1; }
}
public Transform[] spawnPoints;
public float timeBetweenWaves = 5f;
private float waveCountdown;
public float WaveCountdown
{
get { return waveCountdown; }
}
private float searchCountdown = 1f;
private SpawnState state = SpawnState.COUNTING;
public SpawnState State
{
get { return state; }
}
void Start()
{
if (spawnPoints.Length == 0)
{
Debug.LogError("No spawn points referenced.");
}
waveCountdown = timeBetweenWaves;
}
void Update()
{
if (state == SpawnState.WAITING)
{
if (!EnemyIsAlive())
{
WaveCompleted();
}
else
{
return;
}
}
if (waveCountdown <= 0)
{
if (state != SpawnState.SPAWNING)
{
StartCoroutine( SpawnWave ( waves[nextWave] ) );
}
}
else
{
waveCountdown -= Time.deltaTime;
}
}
void WaveCompleted()
{
Debug.Log("Wave Completed!");
state = SpawnState.COUNTING;
waveCountdown = timeBetweenWaves;
if (nextWave + 1 > waves.Length - 1)
{
nextWave = 0;
Debug.Log("ALL WAVES COMPLETE! Looping...");
}
else
{
nextWave++;
}
}
bool EnemyIsAlive()
{
searchCountdown -= Time.deltaTime;
if (searchCountdown <= 0f)
{
searchCountdown = 1f;
if (GameObject.FindGameObjectWithTag("Enemy") == null)
{
return false;
}
}
return true;
}
IEnumerator SpawnWave(Wave _wave)
{
Debug.Log("Spawning Wave: " + _wave.name);
state = SpawnState.SPAWNING;
for (int i = 0; i < _wave.count; i++)
{
SpawnEnemy(_wave.enemy);
yield return new WaitForSeconds( 1f/_wave.rate );
}
state = SpawnState.WAITING;
yield break;
}
void SpawnEnemy(Transform _enemy)
{
Debug.Log("Spawning Enemy: " + _enemy.name);
Transform _sp = spawnPoints[ Random.Range (0, spawnPoints.Length) ];
Instantiate(_enemy, _sp.position, _sp.rotation);
}
}
From what I can see is you're also changing the Z position of the bat. Generally you would not want to do that in a 2D game cause it can go behind stuff as is happening there. In the code I did notice that you are using random points in the world so you would want to check the Z position of those points and change them to 0 or 1.Here's the Image of what you need to change on the points! Hope this helps!

How to prevent same prefab from spawning twice in a row in Unity

Unity beginner here, I have a random prefab spawner attached to my game in Unity which randomly spawns 3 prefabs. The problem is, sometimes I get the same prefab like 5 times in a row. How can I prevent the same prefab from spawning twice in a row? Here is my code:
public class randomspawnscript : MonoBehaviour
{
public GameObject prefab1, prefab2, prefab3;
public float spawnRate = 2f;
float nextSpawn = 0f;
int whatToSpawn;
void Update()
{
if (collisionbutton.end != true || gameoverscreenrestart.restartPressed==true || gameovermainmenu.menuPressed==true)
{
if (Time.time > nextSpawn)
{
whatToSpawn = Random.Range(1, 4);
Debug.Log(whatToSpawn);
switch (whatToSpawn)
{
case 1:
Instantiate(prefab1, transform.position, Quaternion.identity);
break;
case 2:
Instantiate(prefab2, transform.position, Quaternion.identity);
break;
case 3:
Instantiate(prefab3, transform.position, Quaternion.identity);
break;
}
nextSpawn = Time.time + spawnRate;
}
}
else
{
return;
}
}
}
A simple way using the Unity's in build Random system is just to create a list of possible generated numbers, and pick a random number from that list, like so:
public class randomspawnscript : MonoBehaviour {
public GameObject prefab1, prefab2, prefab3;
public float spawnRate = 2f;
float nextSpawn = 0f;
int whatToSpawn;
private void Awake() {
// To not get a null ref error when generating the controlled random
// for the first time.
whatToSpawn = 0;
}
void Update() {
if (/* ... */) {
if (Time.time > nextSpawn) {
whatToSpawn = GetControlledRandom();
Debug.Log(whatToSpawn);
switch (whatToSpawn) {
//...
}
nextSpawn = Time.time + spawnRate;
}
} else {
return;
}
}
int GetControlledRandom() {
List<int> possibleChoices = new List<int> {
1, 2, 3
};
// Removes what was spawned before from the possible choices.
possibleChoices.Remove(whatToSpawn);
return possibleChoices[Random.Range(0, possibleChoices.Count)];
}
}
Alternatively, the more simpler way is to just keep generating a number until you get the one you are satisfied with, like so:
int RetardedControlledRandom() {
int generatedNumber;
do {
generatedNumber = Random.Range(1, 4);
} while (generatedNumber == whatToSpawn);
return generatedNumber;
}
This can help if you decide to use the .NET provided System.Random instead.
Also, note that currently most of your values/variables are hardcode.
(Aka it does not dynamically suit to spawning more than 4 types of prefab)
Unity Inspector accepts an array too, so you can make use of that and refactor your code like so:
public class randomspawnscript : MonoBehaviour {
public GameObject[] possibleSpawnPrefabs;
public float spawnRate = 2f;
float nextSpawn = 0f;
int whatToSpawn;
private void Awake() {
whatToSpawn = 0;
}
void Update() {
if (collisionbutton.end != true || gameoverscreenrestart.restartPressed == true || gameovermainmenu.menuPressed == true) {
if (Time.time > nextSpawn) {
whatToSpawn = GetControlledRandom();
Debug.Log(whatToSpawn);
var prefabToSpawn = possibleSpawnPrefabs[whatToSpawn];
Instantiate(prefabToSpawn, transform.position, Quaternion.identity);
nextSpawn = Time.time + spawnRate;
}
} else {
return;
}
}
int GetControlledRandom() {
List<int> possibleChoices = new List<int>();
for (int i = 0; i < possibleSpawnPrefabs.Length; ++i) {
possibleChoices.Add(i);
}
// Removes what was spawned before from the possible choices.
possibleChoices.Remove(whatToSpawn);
return possibleChoices[Random.Range(0, possibleChoices.Count)];
}
}
Well, just make a statement that checks the new randomized Prefab with the previous randomized prefab.
For the lazy code, you can just
GameObject previousPrefab;
and in Randomization, set the previousPrefab to the randomized prefab.
and in next Randomization, check if the previousPrefab == randomizedPrefab, if yes,
randomize again.
^ Also to achieve something like this you have to create a method from your Update() section and call it in Update() so you can call the method again if the previousPrefab is the same as the randomized one.

How can I prevent a certain piece of code from running when my player reaches a specific score for a certain time?

I'm currently developing a game in Unity and I have a problem. When my player reaches a certain score, in this case, the score of 5 I change the way the obstacles encounter behave. However, for some reason on certain specific occasions when the player reaches the score of 5, I'm assuming when the score of 5 is reached at the exact same time as when the obstacles are being spawned the Obstacles spawn according to the the behaviour required before the score reached 5 but move according to the behaviour required after the score reached 5 instantly as the score of 5 is reached. This shouldn't happen. As the score of 5 is reached the game should keep the behaviour of the obstacles the same as if the score was still smaller than 5 for a second and then switch.
I've already tried to using a coroutine to solve this issue as shown in the code below, however this obviously doesn't work unless I find a way to put the entire class into the coroutine, which will be very messy. I've also tried to suspend the spawning of the obstacles for a second while the score increments from 4 to 5 using a coroutine in the class responsible for spawning the obstacles. However this didn't work
This is the class responsible for the movement of the obstacles:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InteractControl : MonoBehaviour, IPooledObject
{
private Rigidbody2D rb;
GameObject target;
Vector3 directionToTarget;
public static int LevelStart = 0;
//public GameObject[] Balls;
Renderer m_Renderer;
public static float moveSpeed = 5f;
public static bool isSlowMotion = true;
public void OnObjectSpawn()
{
if (ScoreScript.scoreValue > 4 && isSlowMotion)
{
moveSpeed = 10f;
}
target = GameObject.FindWithTag("White Ball");
rb = GetComponent<Rigidbody2D>();
MoveInteract(moveSpeed);
}
void MoveInteract(float moveSpeed)
{
if (target != null)
{
if (ScoreScript.scoreValue > 4 && ScoreScript.scoreValue < 11 && BallSpawnerControl.LevelTrans > 1)
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
else if (ScoreScript.scoreValue < 4)
{
directionToTarget = new Vector3(0, -1, 0);
rb.velocity = new Vector2(0, directionToTarget.y * moveSpeed);
}
}
else
{
GameObject.FindWithTag("ColouredBall Highress").SetActive(false);
}
}
void Update()
{
if (target != null)
{
if (ScoreScript.scoreValue > 10) //Determine when RedBall goes from going down in a straight line to following white ball
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
}
}
}
This is the class responsible for the spawning of the obstacles:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/*
* ObjectPooler.Instance.SpawnFromPool("Ball", Posi, Quaternion.identity );
* ObjectPooler.Instance.SpawnFromPool("Star", Posi, Quaternion.identity );
*/
public class BallSpawnerControl : MonoBehaviour
{
public static bool spawnAllowed;
public static int TimerOn = 1;
public Transform[] spawnPoints;
// public GameObject[] interact;
int randomSpawnPoint, Interact;
int index = 1;
ObjectPooler objectPooler;
public static int LevelTrans = 1;
// Use this for initialization
public void Start()
{
objectPooler = ObjectPooler.Instance;
spawnAllowed = true;
InvokeRepeating("SpawnAInteract", 0f, 1f);
}
void SpawnAInteract()
{
// Change this if statement to only run 1 second after the transition to level 2 has been initiated
if (spawnAllowed)
{
if(ScoreScript.scoreValue > 4 && LevelTrans == 1)
{
StartCoroutine(LevelTransition());
}
else
{
if (index % 5 != 0)
{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
Interact = 1;
// var i = Instantiate(interact[Interact], spawnPoints[randomSpawnPoint].position, Quaternion.identity);
objectPooler.SpawnFromPool("Ball", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
//randomSpawnPoint = Random.Range(0, spawnPoints.Length);
index++;
}
/*if (index % 5 != 0)
{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
objectPooler.SpawnFromPool("Clock", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
} */
else
{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
Interact = 0;
// var i = Instantiate(interact[Interact], spawnPoints[randomSpawnPoint].position, Quaternion.identity);
objectPooler.SpawnFromPool("Star", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
//if (TimerOn == 1)
//{
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
objectPooler.SpawnFromPool("Clock", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
randomSpawnPoint = Random.Range(0, spawnPoints.Length);
objectPooler.SpawnFromPool("Heart", spawnPoints[randomSpawnPoint].position, Quaternion.identity);
// TimerOn++;
// }
index++;
}
}
}
}
private IEnumerator LevelTransition()
{
yield return new WaitForSeconds(1f);
LevelTrans++;
Debug.Log( "Level Trans :" + LevelTrans);
}
}
Thanks in advance
This is the interface from which OnObjectspawn derives from:
using UnityEngine;
public interface IPooledObject
{
void OnObjectSpawn();
}

Bullet Shooting in unity

Hi i have below cod for my android project and when i look Up and Down and shoot a bullet the bullet shooting direction be wrong where is the problem?
here is a vidoe of my project.
http://www.mediafire.com/file/9xhxvyxds4cyego/2016-11-27_15-07-39.mp4
FirstPerson
using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
using UnityStandardAssets.Utility;
using Random = UnityEngine.Random;
namespace UnityStandardAssets.Characters.FirstPerson
{
[RequireComponent(typeof (CharacterController))]
[RequireComponent(typeof (AudioSource))]
public class FirstPersonController : MonoBehaviour
{
[SerializeField] private bool m_IsWalking;
[SerializeField] private float m_WalkSpeed;
[SerializeField] private float m_LookSpeed=4;
[SerializeField] private float m_RunSpeed;
[SerializeField] [Range(0f, 1f)] private float m_RunstepLenghten;
[SerializeField] private float m_JumpSpeed;
[SerializeField] private float m_StickToGroundForce;
[SerializeField] private float m_GravityMultiplier;
[SerializeField] private MouseLook m_MouseLook;
[SerializeField] private bool m_UseFovKick;
[SerializeField] private FOVKick m_FovKick = new FOVKick();
[SerializeField] private bool m_UseHeadBob;
[SerializeField] private CurveControlledBob m_HeadBob = new CurveControlledBob();
[SerializeField] private LerpControlledBob m_JumpBob = new LerpControlledBob();
[SerializeField] private float m_StepInterval;
[SerializeField] private AudioClip[] m_FootstepSounds; // an array of footstep sounds that will be randomly selected from.
[SerializeField] private AudioClip m_JumpSound; // the sound played when character leaves the ground.
[SerializeField] private AudioClip m_LandSound; // the sound played when character touches back on ground.
private Camera m_Camera;
private bool m_Jump;
private float m_YRotation;
private Vector2 m_Input;
private Vector3 m_MoveDir = Vector3.zero;
private CharacterController m_CharacterController;
private CollisionFlags m_CollisionFlags;
private bool m_PreviouslyGrounded;
private Vector3 m_OriginalCameraPosition;
private float m_StepCycle;
private float m_NextStep;
private bool m_Jumping;
private AudioSource m_AudioSource;
public GameObject AK;
// Use this for initialization
private void Start()
{
Instantiate(AK);
m_CharacterController = GetComponent<CharacterController>();
m_Camera = Camera.main;
m_OriginalCameraPosition = m_Camera.transform.localPosition;
m_FovKick.Setup(m_Camera);
m_HeadBob.Setup(m_Camera, m_StepInterval);
m_StepCycle = 0f;
m_NextStep = m_StepCycle/2f;
m_Jumping = false;
m_AudioSource = GetComponent<AudioSource>();
m_MouseLook.Init(transform , m_Camera.transform);
}
// Update is called once per frame
private void Update()
{
RotateView();
// the jump state needs to read here to make sure it is not missed
if (!m_Jump)
{
m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
}
if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
{
StartCoroutine(m_JumpBob.DoBobCycle());
PlayLandingSound();
m_MoveDir.y = 0f;
m_Jumping = false;
}
if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
{
m_MoveDir.y = 0f;
}
m_PreviouslyGrounded = m_CharacterController.isGrounded;
}
private void PlayLandingSound()
{
m_AudioSource.clip = m_LandSound;
m_AudioSource.Play();
m_NextStep = m_StepCycle + .5f;
}
private void FixedUpdate()
{
float speed;
GetInput(out speed);
// always move along the camera forward as it is the direction that it being aimed at
Vector3 desiredMove = transform.forward*m_Input.y + transform.right*m_Input.x;
// get a normal for the surface that is being touched to move along it
RaycastHit hitInfo;
Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo,
m_CharacterController.height/2f);
desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;
m_MoveDir.x = desiredMove.x*speed;
m_MoveDir.z = desiredMove.z*speed;
if (m_CharacterController.isGrounded)
{
m_MoveDir.y = -m_StickToGroundForce;
if (m_Jump)
{
m_MoveDir.y = m_JumpSpeed;
PlayJumpSound();
m_Jump = false;
m_Jumping = true;
}
}
else
{
m_MoveDir += Physics.gravity*m_GravityMultiplier*Time.fixedDeltaTime;
}
m_CollisionFlags = m_CharacterController.Move(m_MoveDir*Time.fixedDeltaTime);
ProgressStepCycle(speed);
UpdateCameraPosition(speed);
}
private void PlayJumpSound()
{
m_AudioSource.clip = m_JumpSound;
m_AudioSource.Play();
}
private void ProgressStepCycle(float speed)
{
if (m_CharacterController.velocity.sqrMagnitude > 0 && (m_Input.x != 0 || m_Input.y != 0))
{
m_StepCycle += (m_CharacterController.velocity.magnitude + (speed*(m_IsWalking ? 1f : m_RunstepLenghten)))*
Time.fixedDeltaTime;
}
if (!(m_StepCycle > m_NextStep))
{
return;
}
m_NextStep = m_StepCycle + m_StepInterval;
PlayFootStepAudio();
}
private void PlayFootStepAudio()
{
if (!m_CharacterController.isGrounded)
{
return;
}
// pick & play a random footstep sound from the array,
// excluding sound at index 0
int n = Random.Range(1, m_FootstepSounds.Length);
m_AudioSource.clip = m_FootstepSounds[n];
m_AudioSource.PlayOneShot(m_AudioSource.clip);
// move picked sound to index 0 so it's not picked next time
m_FootstepSounds[n] = m_FootstepSounds[0];
m_FootstepSounds[0] = m_AudioSource.clip;
}
private void UpdateCameraPosition(float speed)
{
Vector3 newCameraPosition;
if (!m_UseHeadBob)
{
return;
}
if (m_CharacterController.velocity.magnitude > 0 && m_CharacterController.isGrounded)
{
m_Camera.transform.localPosition =
m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude +
(speed*(m_IsWalking ? 1f : m_RunstepLenghten)));
newCameraPosition = m_Camera.transform.localPosition;
newCameraPosition.y = m_Camera.transform.localPosition.y - m_JumpBob.Offset();
}
else
{
newCameraPosition = m_Camera.transform.localPosition;
newCameraPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
}
m_Camera.transform.localPosition = newCameraPosition;
}
private void GetInput(out float speed)
{
// Read input
float horizontal = CrossPlatformInputManager.GetAxisRaw("Horizontal");
float vertical = CrossPlatformInputManager.GetAxisRaw("Vertical");
bool waswalking = m_IsWalking;
#if !MOBILE_INPUT
// On standalone builds, walk/run speed is modified by a key press.
// keep track of whether or not the character is walking or running
m_IsWalking = !Input.GetKey(KeyCode.LeftShift);
#endif
// set the desired speed to be walking or running
speed = m_IsWalking ? m_WalkSpeed : m_RunSpeed;
m_Input = new Vector2(horizontal, vertical);
// normalize input if it exceeds 1 in combined length:
if (m_Input.sqrMagnitude > 1)
{
m_Input.Normalize();
}
// handle speed change to give an fov kick
// only if the player is going to a run, is running and the fovkick is to be used
if (m_IsWalking != waswalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0)
{
StopAllCoroutines();
StartCoroutine(!m_IsWalking ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown());
}
}
private void RotateView()
{
#if !MOBILE_INPUT
m_MouseLook.LookRotation (transform, m_Camera.transform);
m_Camera.transform.localEulerAngles = new Vector3 (-m_MouseLook.y, m_Camera.transform.localEulerAngles.y,
m_Camera.transform.localEulerAngles.z);
transform.localEulerAngles = new Vector3 (0, m_MouseLook.x, 0);
#else
Vector2 m_MouseLook= new Vector2( CrossPlatformInputManager.GetAxisRaw("HorizontalLook")
,CrossPlatformInputManager.GetAxisRaw("VerticalLook"));
float Camx=m_Camera.transform.localEulerAngles.x;
if((Camx>280 && Camx<=360) ||
(Camx >=0 && Camx<80) ||
(Camx>=80 && Camx<180 && m_MouseLook.y>0) ||
(Camx>180 && Camx<=280 && m_MouseLook.y<0))
{
m_Camera.transform.localEulerAngles += new Vector3 (-m_MouseLook.y*m_LookSpeed, m_Camera.transform.localEulerAngles.y,
m_Camera.transform.localEulerAngles.z);
// AK.transform.localEulerAngles=m_Camera.transform.localEulerAngles;
}
transform.localEulerAngles += new Vector3 (0, m_MouseLook.x*m_LookSpeed, 0);
#endif
m_YRotation = m_MouseLook.y;
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
Rigidbody body = hit.collider.attachedRigidbody;
//dont move the rigidbody if the character is on top of it
if (m_CollisionFlags == CollisionFlags.Below)
{
return;
}
if (body == null || body.isKinematic)
{
return;
}
body.AddForceAtPosition(m_CharacterController.velocity*0.1f, hit.point, ForceMode.Impulse);
}
}
}
Joystick cod-------------///////////////
using System;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UnityStandardAssets.CrossPlatformInput
{
public class Joystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
public enum AxisOption
{
// Options for which axes to use
Both, // Use both
OnlyHorizontal, // Only horizontal
OnlyVertical // Only vertical
}
public int MovementRange = 100;
public AxisOption axesToUse = AxisOption.Both; // The options for the axes that the still will use
public string horizontalAxisName = "Horizontal"; // The name given to the horizontal axis for the cross platform input
public string verticalAxisName = "Vertical"; // The name given to the vertical axis for the cross platform input
Vector3 m_StartPos;
bool m_UseX; // Toggle for using the x axis
bool m_UseY; // Toggle for using the Y axis
CrossPlatformInputManager.VirtualAxis m_HorizontalVirtualAxis; // Reference to the joystick in the cross platform input
CrossPlatformInputManager.VirtualAxis m_VerticalVirtualAxis; // Reference to the joystick in the cross platform input
void OnEnable()
{
CreateVirtualAxes();
}
void Start()
{
m_StartPos = transform.position;
}
void UpdateVirtualAxes(Vector3 value)
{
var delta = m_StartPos - value;
delta.y = -delta.y;
delta /= MovementRange;
if (m_UseX)
{
m_HorizontalVirtualAxis.Update(-delta.x);
}
if (m_UseY)
{
m_VerticalVirtualAxis.Update(delta.y);
}
}
void CreateVirtualAxes()
{
// set axes to use
m_UseX = (axesToUse == AxisOption.Both || axesToUse == AxisOption.OnlyHorizontal);
m_UseY = (axesToUse == AxisOption.Both || axesToUse == AxisOption.OnlyVertical);
// create new axes based on axes to use
if (m_UseX)
{
m_HorizontalVirtualAxis = new CrossPlatformInputManager.VirtualAxis(horizontalAxisName);
CrossPlatformInputManager.RegisterVirtualAxis(m_HorizontalVirtualAxis);
}
if (m_UseY)
{
m_VerticalVirtualAxis = new CrossPlatformInputManager.VirtualAxis(verticalAxisName);
CrossPlatformInputManager.RegisterVirtualAxis(m_VerticalVirtualAxis);
}
}
public void OnDrag(PointerEventData data)
{
Vector3 newPos = Vector3.zero;
if (m_UseX)
{
int delta = (int)(data.position.x - m_StartPos.x);
delta = Mathf.Clamp(delta, - MovementRange, MovementRange);
newPos.x = delta;
}
if (m_UseY)
{
int delta = (int)(data.position.y - m_StartPos.y);
delta = Mathf.Clamp(delta, -MovementRange, MovementRange);
newPos.y = delta;
}
transform.position = new Vector3(m_StartPos.x + newPos.x, m_StartPos.y + newPos.y, m_StartPos.z + newPos.z);
UpdateVirtualAxes(transform.position);
}
public void OnPointerUp(PointerEventData data)
{
transform.position = m_StartPos;
UpdateVirtualAxes(m_StartPos);
}
public void OnPointerDown(PointerEventData data) { }
void OnDisable()
{
// remove the joysticks from the cross platform input
if (m_UseX)
{
m_HorizontalVirtualAxis.Remove();
}
if (m_UseY)
{
m_VerticalVirtualAxis.Remove();
}
}
}
}
Shooting Bullet
#pragma strict
//---------------------------------------------------------
//---------------------------------------------------------
var Mig29_Fulcrum:GameObject;
var AK:Rigidbody;
var muzzel:GameObject;
var bullet:Rigidbody;
var Speed:int=700;
private var Fire:int=0;
private var Shooting:boolean =false;
private var gun:GameObject;
private var fireDelay:float = 0f; // the delay between shots
function Start () {
gun=GameObject.FindWithTag("MyGun");
//var AkGun:Rigidbody=Instantiate(AK,this.transform.position,this.transform.rotation);
//var b:Rigidbody=Instantiate(bullet,this.transform.position,this.transform.rotation);
}
function Update () {
if(Input.GetButtonDown("Fire2"))
{
//gun.GetComponent.<Animation>().Play("Jump");
Shooting=true;
}
if(Input.GetButtonDown("Fire1"))
{
Shooting=false;
}
if(Shooting)
{
AutoFire(0.08f);
}
}
function FireWeapon()
{
Debug.Log("Fire!!!");
GetComponent.<AudioSource>().Play();
gun.GetComponent.<Animation>().Play("GunFire");
var m:GameObject=Instantiate(muzzel,this.transform.position,this.transform.rotation);
m.transform.Rotate(Vector3(-90,0,0));
m.transform.Rotate(Vector3(0,Random.Range(0,180),0));
Destroy(m,0.015);
var b:Rigidbody=Instantiate(bullet,this.transform.position,this.transform.rotation);
b.AddForce(this.transform.forward*Speed);
}
// The function below activates the FireWeapon function
function AutoFire( fireRate:float)
{
if (fireDelay < fireRate)
{
fireDelay += Time.deltaTime;
}
if (fireDelay >= fireRate)
{
FireWeapon();
fireDelay = 0f;
}
}
Judging by the video, the problem is that your bullets are fired based on the position and orientation of the camera, not the gun. This is normally preferable in most first person shooter games (eg. Counter-Strike and similar), but maybe not in your case (since you're using mobile joystick controls).
This behavior is caused by the following code:
var b:Rigidbody=Instantiate(bullet,this.transform.position,this.transform.rotation);
b.AddForce(this.transform.forward*Speed);
Since you're using the position and rotation of this.transform, the script refers to the transform of the camera you attached the script to.
If you wish your game to behave differently, you should consider referring to the transform component of the gun instead (conveniently, in your cased stored in the variable gun):
var b:Rigidbody=Instantiate(bullet,gun.transform.position,gun.transform.rotation);
b.AddForce(gun.transform.forward*Speed);
Note that this might not work if your gun's anchor isn't at the muzzle and its forward vector doesn't point in the direction you want the bullet to come out. In that case, you might want to add to the gun an empty child GameObject that's properly positioned and oriented.

How to Unity create your own button to control the player on mobile device

i am not sure how to do this ,my goal is to create a button that will control the player on the plane for the mobile touch devices.I created the button I am trying to make it to control the player but i am failing here is my player c# script
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour
{
public float speed = 500f, jumpHeight = 500f;
Transform myTrans;
Rigidbody2D myBody;
Vector2 movement;//used as temp holder variable before applying to velocity
bool isGrounded = true;
void Start ()
{
myTrans = this.transform;
myBody = this.GetComponent<Rigidbody2D>() ;
}
void Update ()
{
//Check if the player is grounded or not
isGrounded = Physics2D.Linecast(myTrans.position,
GameObject.Find(this.name+"/tag_ground").transform.position,
LayerMask.NameToLayer("Player"));
//Just for visualization, not needed for gameplay
Debug.DrawLine (myTrans.position,
GameObject.Find(this.name+"/tag_ground").transform.position,
Color.red);
//Works for keyboards and joysticks
#if !UNITY_ANDROID && !UNITY_IPHONE && !UNITY_BLACKBERRY && !UNITY_WINRT
Move (Input.GetAxisRaw("Horizontal"));
if (Input.GetButtonDown ("Jump"))
Jump ();
#endif
}
//
//Separate Move and Jump so they can be called externally by TouchButtons
//
public void Move(float horizontal_input)
{
movement = myBody.velocity;
if(isGrounded)//we can only move left and right if on the ground
movement.x = horizontal_input * speed * Time.deltaTime;
//Apply the movement to the player
myBody.velocity = movement;
}
public void Jump()//we can only jump if on the ground
{
if(isGrounded)
myBody.velocity += jumpHeight * Vector2.up * Time.deltaTime;
}
}
here is the touch logic script
using UnityEngine;
using System.Collections;
public class TouchLogicV2 : MonoBehaviour
{
public static int currTouch = 0;//so other scripts can know what touch is currently on screen
[HideInInspector]
public int touch2Watch = 64;
private new GUITexture guiTexture;
public virtual void Update()//If your child class uses Update, you must call base.Update(); to get this functionality
{
//is there a touch on screen?
if(Input.touches.Length <= 0)
{
OnNoTouches();
}
else //if there is a touch
{
//loop through all the the touches on screen
for(int i = 0; i < Input.touchCount; i++)
{
currTouch = i;
//executes this code for current touch (i) on screen
if(this.guiTexture != null && (this.guiTexture.HitTest(Input.GetTouch(i).position)))
{
//if current touch hits our guitexture, run this code
if(Input.GetTouch(i).phase == TouchPhase.Began)
{
OnTouchBegan();
touch2Watch = currTouch;
}
if(Input.GetTouch(i).phase == TouchPhase.Ended)
{
OnTouchEnded();
}
if(Input.GetTouch(i).phase == TouchPhase.Moved)
{
OnTouchMoved();
}
if(Input.GetTouch(i).phase == TouchPhase.Stationary)
{
OnTouchStayed();
}
}
//outside so it doesn't require the touch to be over the guitexture
switch(Input.GetTouch(i).phase)
{
case TouchPhase.Began:
OnTouchBeganAnywhere();
break;
case TouchPhase.Ended:
OnTouchEndedAnywhere();
break;
case TouchPhase.Moved:
OnTouchMovedAnywhere();
break;
case TouchPhase.Stationary:
OnTouchStayedAnywhere();
break;
}
}
}
}
//the default functions, define what will happen if the child doesn't override these functions
public virtual void OnNoTouches(){}
public virtual void OnTouchBegan(){print (name + " is not using OnTouchBegan");}
public virtual void OnTouchEnded(){}
public virtual void OnTouchMoved(){}
public virtual void OnTouchStayed(){}
public virtual void OnTouchBeganAnywhere(){}
public virtual void OnTouchEndedAnywhere(){}
public virtual void OnTouchMovedAnywhere(){}
public virtual void OnTouchStayedAnywhere(){}
}
I am following the touchlogic tuts but am struggling to move the player on mobile.Any with good examples on touch input is welcomed to give me the links for examples.thanks