Unity: Problem with Index was outside the bounds of the array - unity3d

I'm drawing using LineRenderer but I enable and disable the gameobject where the script is at different times.
The first enable it works perfect, after I disable and enable, I get this error
IndexOutOfRangeException: Index was outside the bounds of the array.
error shows to this line of code
Vector2 touchPos = Camera.main.ScreenToWorldPoint(Input.touches[0].position);
Here is all the code
public GameObject linePrefab;
private Line activeLine;
private void Update()
{
if (Input.touchCount > 0)
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
GameObject lineGO = Instantiate(linePrefab);
activeLine = lineGO.GetComponent<Line>();
}
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
activeLine = null;
}
}
if (activeLine != null)
{
Vector2 touchPos = Camera.main.ScreenToWorldPoint(Input.touches[0].position);
activeLine.UpdateLine(touchPos);
}
}

You're assuming the user is touching the screen in your code.
You need to check if there are any active touches before processing the touch position. Specifically, you can add to your if check whether or not Input.touchCount > 0

Related

Missing Reference Exception Photon Pun

I am Working on an multiplayer fps game the code throws an missing reference exception in the line given below the error doesn't show up when there is only one player in the room but it starts coming as soon as another player joins the room
private IEnumerator Shoot()
{
ammoLeft -= 1;
animator.SetBool("fire", true);
RaycastHit hit;
if (Physics.Raycast(playerCam.position, playerCam.forward, out hit, range))
{
//Missing Reference Expection The transform you are accessing is destroyed
//code works in singleplayer
if (hit.transform.tag == "Player" && hit.transform != null)
{
HealthManager HealthScript = hit.transform.gameObject.GetComponent<HealthManager>();
if (HealthScript != null)
{
HealthScript.TakeDamage(damage);
}
}
}
yield return new WaitForSeconds(0.3f);
animator.SetBool("fire", false);
if (ammoLeft <= 0f)
{
StartCoroutine("Reload");
}
Error in this line
Physics.Raycast(playerCam.position, playerCam.forward, out hit, range)
I have checked if my camera is null but the problem doesn't fix so I am clueless
private void Awake()
{
if (!pv.IsMine)
{
Destroy(ui);
}
if (playerCam == null)
{
playerCam = FindObjectOfType<Camera>().transform;
}
ammoLeft = magazineSize;
animator = GetComponent<Animator>();
}
Inspector Window
https://i.stack.imgur.com/Tc69B.png

How to show a tracking line from where the model is placed in Augmented Reality?

I am looking to show a line in my app from where the model is placed so that the user knows position where the model is kept in real world. When user changes device camera away from model the line gets turned on to show where the model is. Similarly it turns off when model is detected. I have attached images to show from a similar app white dotted lines show the path. Notice how the lines disappear when the model is detected.
LineRenderer lins;
public GameObject Lineprefab;
private GameObject newline;
public Transform startpoint;
public Renderer m_rend1;
bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
{
List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);
if (hitResults.Count > 0 && check==true)
{
foreach (var hitResult in hitResults)
{
Debug.Log ("Got hit!");
//obj.Hideplane();
Genplanes.SetActive(false);
if (Select == 0) {
Debug.Log("hit-zero!");
Instantiate(Instaobj[0], ForSelect);
check = false;
}
if (Select == 1) {
Debug.Log("hit-one!");
Instantiate(Instaobj[1], ForSelect);
check = false;
}
if (Select == 2) {
Debug.Log("hit-two!");
Instantiate(Instaobj[2], ForSelect);
check = false;
}
m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
obj.StopPlaneTracking();
}
}
return false;
}
private void Start()
{
spawngenerator();
newline.SetActive(false);
m_rend1 = GetComponent<MeshRenderer>();
}
void spawngenerator()
{
GameObject newline = Instantiate(Lineprefab);
lins = newline.GetComponent<LineRenderer>();
}
private void LateUpdate()
{
lins.SetPosition(0, startpoint.position);
lins.SetPosition(1, m_HitTransform.position);
if( m_rend1.isVisible==true)
{
Debug.Log("Render is Visible");
newline.SetActive(false);
}
else if( m_rend1.isVisible==false)
{
newline.SetActive(true);
Debug.Log("It is InVisible");
Debug.Log("Render is InVisible");
}
}
void Update () {
#if UNITY_EDITOR //we will only use this script on the editor side, though there is nothing that would prevent it from working on device
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
//we'll try to hit one of the plane collider gameobjects that were generated by the plugin
//effectively similar to calling HitTest with ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent
if (Physics.Raycast (ray, out hit, maxRayDistance, collisionLayer)) {
//we're going to get the position from the contact point
m_HitTransform.position = hit.point;
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
//and the rotation from the transform of the plane collider
m_HitTransform.rotation = hit.transform.rotation;
}
}
#else
if (Input.touchCount > 0 && m_HitTransform != null )
{
var touch = Input.GetTouch(0);
if ((touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved) && !EventSystem.current.IsPointerOverGameObject(touch.fingerId))
{
var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
ARPoint point = new ARPoint {
x = screenPosition.x,
y = screenPosition.y
};
// prioritize reults types
ARHitTestResultType[] resultTypes = {
//ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingGeometry,
ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent,
// if you want to use infinite planes use this:
//ARHitTestResultType.ARHitTestResultTypeExistingPlane,
//ARHitTestResultType.ARHitTestResultTypeEstimatedHorizontalPlane,
//ARHitTestResultType.ARHitTestResultTypeEstimatedVerticalPlane,
//ARHitTestResultType.ARHitTestResultTypeFeaturePoint
};
foreach (ARHitTestResultType resultType in resultTypes)
{
if (HitTestWithResultType (point, resultType))
{
return;
}
}
}
}
#endif
}
.
First, I 'd start with checking if the model is within the bounding box of the camera https://docs.unity3d.com/ScriptReference/Renderer-isVisible.html
if the object is not visible (isVisible == false), create a line renderer from object position to wherever it should end.
The end point could be a camera child place just in front of it, so it looks like it starts from the user to the object.

Need to disable Particle System as soon as it stops playing

I am trying to implement a Flame Thrower. I have setup the Particle System for flame. It is pooled object. It is not the child of the Flame Thrower. When I press the Fire button the particle system starts and when the button is up it stops. But a problem arised that when player is moving the particle system doesn't move . this was solved by adding the below line
particles.transform.position = transform.GetChild(0).position;
But the I discovered another problem that when rotating the player(This is a 2D sidescroller game) the particles are rotated with it instantly. So when the player changes the direction current particles are stopped and a new particle is activated and played. But now the problem is whenever I change the direction while pressing Fire buttons new objects are created.
The code of my flame thrower is
using UnityEngine;
public class FlameThrower : Gun
{
private ParticleSystem particles;
private int direction = 0;
private bool isFiring = false;
public override void Update()
{
if(shoot)
{
InitShoot();
}
else
{
StopFire();
}
}
public override void InitShoot()
{
if(!isFiring)
{
SelectDirection();
Fire();
}
//Check direction has changed
if(direction != playerManager.direction)
{
StopFire();
}
if(particles != null)
{
particles.transform.position = transform.GetChild(0).position;
}
}
public override void Fire()
{
isFiring = true;
direction = playerManager.direction;
InstantiateParticles(weapon.bulletName, transform.GetChild(0).position, rotation);
}
public override void SelectDirection()
{
if (playerManager.direction == 1)
{
rotation = Quaternion.Euler(transform.rotation.x, transform.rotation.y, -90);
}
else if (playerManager.direction == -1)
{
rotation = Quaternion.Euler(transform.rotation.x, transform.rotation.y, 90);
}
}
public override void InstantiateParticles(string name, Vector3 position, Quaternion rotation)
{
GameObject bullet = ObjectPooler.instance.GetObject(name);
while (bullet == null)
{
ObjectPooler.instance.CreateObject(name);
bullet = ObjectPooler.instance.GetObject(name);
}
if (bullet != null)
{
particles = bullet.GetComponent<ParticleSystem>();
//Set Position and rotation
bullet.transform.position = position;
bullet.transform.rotation = rotation;
bullet.SetActive(true);
particles.Play();
}
}
private void StopFire()
{
if (particles != null)
{
isFiring = false;
particles.Stop();
if(!particles.isPlaying)
{
particles.gameObject.SetActive(false);
particles = null;
}
}
}
}
The problem is that in the function StopFire() it checks whether particle is playing or not. If it is not playing it will disable the Gameobject. But it that part doesn't execute since it is checked soon after particles is stopped and it will still be playing. I want this particle system to be disabled as soon as it stops playing
It seems that the particle system is rendering in local space, that's why it rotates with the object.
Change the Simulation Space to World.
For the other issue, if you disable the game object then particles which are already emitted will disappear. And if you deactivates them with a delay (using Invoke or similar) then within that delay new particles can be emitted.
The best way to handle this is to stop the emission, not deactivating the game object. You can do this in inspector or via code. myParticles.emission.enabled
using UnityEngine;
public class ParticleSystemControllerWindow : MonoBehaviour
{
ParticleSystem system
{
get
{
if (_CachedSystem == null)
_CachedSystem = GetComponent<ParticleSystem>();
return _CachedSystem;
}
}
private ParticleSystem _CachedSystem;
public Rect windowRect = new Rect(0, 0, 300, 120);
public bool includeChildren = true;
void OnGUI()
{
windowRect = GUI.Window("ParticleController".GetHashCode(), windowRect, DrawWindowContents, system.name);
}
void DrawWindowContents(int windowId)
{
if (system)
{
GUILayout.BeginHorizontal();
GUILayout.Toggle(system.isPlaying, "Playing");
GUILayout.Toggle(system.isEmitting, "Emitting");
GUILayout.Toggle(system.isPaused, "Paused");
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Play"))
system.Play(includeChildren);
if (GUILayout.Button("Pause"))
system.Pause(includeChildren);
if (GUILayout.Button("Stop Emitting"))
system.Stop(includeChildren, ParticleSystemStopBehavior.StopEmitting);
if (GUILayout.Button("Stop & Clear"))
system.Stop(includeChildren, ParticleSystemStopBehavior.StopEmittingAndClear);
GUILayout.EndHorizontal();
includeChildren = GUILayout.Toggle(includeChildren, "Include Children");
GUILayout.BeginHorizontal();
GUILayout.Label("Time(" + system.time + ")");
GUILayout.Label("Particle Count(" + system.particleCount + ")");
GUILayout.EndHorizontal();
}
else
GUILayout.Label("No particle system found");
GUI.DragWindow();
}
}
This might help you in playing,pausing and fully stopping your particle system from emitting particles.
Hope i helped.

NullReferenceException and don't know how to fix it

Okay, I am making a simple game mechanic where you are a ball rolling along a small panel. On the edge of the panel are 8 child objects. 4 of them are triggers on the edges of the panel, and 4 of them are empty game objects 1 unit away from each edge of the panel for the location of the next panel prefab to spawn at. The ball has a trigger on it that detects the location of the empty game objects to tell the panel prefab where to spawn. When the ball enters a specific trigger frm the panel the ball is suppose to instantiate a panel prefab on the location that I assign based on the trigger the ball enters. Here is my code:
public GameObject panelPrefab;
Transform frontSpawn;
Transform backSpawn;
Transform leftSpawn;
Transform rightSpawn;
private bool allowSpawn;
void Awake()
{
allowSpawn = true;
}
void OnTriggerStay(Collider spawn)
{
if (spawn.gameObject.tag == "FrontSpawn")
{
frontSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "BackSpawn")
{
backSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "LeftSpawn")
{
leftSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "RightSpawn")
{
rightSpawn = spawn.transform;
}
}
void OnTriggerEnter (Collider other)
{
if (other.gameObject.tag == "Front" && allowSpawn == true)
{
Instantiate (panelPrefab, frontSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Back" && allowSpawn == true)
{
Instantiate (panelPrefab, backSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Left" && allowSpawn == true)
{
Instantiate (panelPrefab, leftSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Right" && allowSpawn == true)
{
Instantiate (panelPrefab, rightSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
}
void OnTriggerExit (Collider other)
{
allowSpawn = true;
}
My issue is on each of the Instantiate calls, I am getting a NullReferenceException. I have the panelPrefab assigned in the unity editor, and I don't know what could be causing this! If anyone can help me here it would be GREATLY appreciated... So thank you in advance!
OnTriggerEnter is called before OnTriggerStay. The error is not due to the panelPrefab object. It might happen that your rightSpawn, leftSpawn etc. objects are null and hence cannot access the transform property of a null object.
Before instantiating verify if rightSpawn etc. is null or not and then access it's position.

How to detect touch in Unity Game Engine (2D)

I have a bomb and want it to explode when touched. I just tried implementing this with ray-casting but something isn't working. I'm using unity 2d settings.
Also I'm programming this on a computer(of course) so is there some setting I have to set to make it recognize mouse clicks as touches?
#pragma strict
var explosion:GameObject;
function Update () {
for (var i = 0; i < Input.touchCount; i++) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
// Construct a ray from the current touch coordinates
var pos:Vector3 = Camera.main.ScreenToWorldPoint (Input.mousePosition);
var hitInfo:RaycastHit2D = Physics2D.Raycast(pos, Vector2.zero);
if (hitInfo != null && hitInfo.collider != null) {
Debug.Log ("I'm hitting "+hitInfo.collider.name);
var whatsHit:GameObject = hitInfo.collider.gameObject;
if(whatsHit.CompareTag("bomb")){
whatsHit.GetComponent(BombScript).Explode(whatsHit.transform.position);
}
} else {
Debug.Log("hitting nothing");
}
}
}
}
function Explode(pos:Vector3){
GameObject.FindGameObjectWithTag("GameController").GetComponent(BombSpawner).spawnBomb = true;
Instantiate(explosion, pos, Quaternion.identity);
Destroy (this.gameObject);
}
The OnMouseDown actually gets raised on touch as well. It, of course, limits your ability to track the finger Id, but if you don't need it then this is perfect since it does allow you to use it on both PC and touch devices with no extra code.