I'm having some discrepancy between playing my unity project inside the editor, and playing the build it makes.
Inside the editor, when I play my game I have code that spawns enemies when my player hits a target spot, which works. The enemies spawn and do what they need to do. However, when I build the project and run it, my player hits the same spot, but nothing appears.
I ran the project in the development mode and it claims I have not set the reference which I thought I had. I mean, if it didn't work, why is it working in the editor?
To try and combat this, I re-imported the assets I'm using. I remade the enemy spawn points. But I still get the same issue.
Has anyone ever came across this before?
If so, how can I fix this issue when it works inside the editor, but not in the build?
Here is my spawning function:
public GameObject SpawnEnemies()
{
Vector3 _position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
// instantiate particel system
// Instantiate(_particle, _position, Quaternion.identity);
audio.PlayOneShot(_appearSound);
_clone = (GameObject)Instantiate(_enemy, _position, transform.rotation);
_ai = _clone.GetComponent<HV_BaseAI>();
_ai._waypoints = _wayPoints;
return _clone;
}
This is controlled by my section class which has the following function:
public List<GameObject> SpawnGroundEnemies()
{
List<GameObject> groundObjectList = new List<GameObject>();
for (int i = 0; i < _spawnPoints.Count; i++)
{
groundObjectList.Add(_spawnPoints[i].SpawnEnemies());
}
return groundObjectList;
}
Which, in turn is controlled by my section controller:
GameObject g, f;
g = GameObject.FindGameObjectWithTag("SectionController");
f = GameObject.FindGameObjectWithTag("SectionController");
HV_SectionController tempSectionControllerGroundEnemies, tempSectionControllerFlyingEnemies;
tempSectionControllerGroundEnemies = g.GetComponent<HV_SectionController>();
tempSectionControllerFlyingEnemies = f.GetComponent<HV_SectionController>();
_groundEnemiesRemaining = tempSectionControllerGroundEnemies._numberOfGroundEnemies.Count;
_flyingEnemiesRemaining = tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Count;
_enemiesRemaining = _groundEnemiesRemaining + _flyingEnemiesRemaining;
if (!_moving)
{
if (_enemiesRemaining == 0)
{
MoveToNextSection();
}
}
if (_moving)
{
if (Vector3.SqrMagnitude(_camera.transform.position - _camNavMesh.destination) < 5.0f)
{
_moving = false;
// spawn the next set of enemies
// need this for each section of the game
// without this, no enemies will spawn
if (CurrentSection == 1)
{
_numberOfGroundEnemies = _sections[0].SpawnGroundEnemies();
_enemiesRemaining = _numberOfGroundEnemies.Count;
}
if (CurrentSection == 2)
{
_numberOfFlyingEnemies = _sections[1].SpawnFlyingEnemies();
_enemiesRemaining = _numberOfFlyingEnemies.Count;
}
if (CurrentSection == 3)
{
_numberOfGroundEnemies = _sections[2].SpawnGroundEnemies();
_enemiesRemaining = _numberOfGroundEnemies.Count;
}
}
}
}
private void MoveToNextSection()
{
if (_currentSection == _sections.Count)
{
_currentSection = 0;
}
_camNavMesh.SetDestination(_sections[_currentSection]._cameraTransform.position);
_lookAtPoint.SetTimer(_sections[_currentSection]._cameraLookAtTarget.position);
_moving = true;
_currentSection += 1;
}
Can anyone see anything i'm doing wrong?
Update
Since this post, I've tried reimporting all of my assets again. I've even created a fresh project and done a fresh build that way, but I still have the same issue. Also, to help, I've take two screen grabs to show what I mean.
First off, the game running in the unity editor:
As you can see, there is 4 skeletons on the bridge. These guys appear when I hit play in the unity editor.
Now, when I build the project, this is same sections:
As you can see, no enemies, but when its a development build, it says I've no reference set. In the output log unity genereates, it gives me this message:
NullReferenceException: Object reference not set to an instance of an
object at HV_SpawnGroundEnemy.SpawnEnemies () [0x00052] in
C:\Users\sean.obrien\Desktop\Medieval Darkride
Level\Assets_scripts\Enemy Scripts\HV_SpawnGroundEnemy.cs:37
at HV_Section.SpawnGroundEnemies () [0x0000d] in
C:\Users\sean.obrien\Desktop\Medieval Darkride
Level\Assets_scripts\Helper Scripts\HV_Section.cs:26
at HV_SectionController.Update () [0x000c2] in
C:\Users\sean.obrien\Desktop\Medieval Darkride
Level\Assets_scripts\Helper Scripts\HV_SectionController.cs:72
Again, this only appears in the built version of the game. When I run this inside Unity, everything works fine. I honestly have no idea why this issue arises when it works fine in the editor but not in the build.
There's most probably two cases here. Either you've not saved your scene yet, or you're not including the correct scene while making the build.
If it's the first case, just save the scene. If it's second, then you need to choose proper scene in the build settings and then rebuild.
Explanation:
You might have saved the scene as some other file, but the build setting does not update the scene file dynamically. It'll still point to the old scene. So you just need to remove the old scene and add the current scene you're using.
Related
So I'm trying to make a 2D Snake game in Unity, which is made from 4 different C# scripts.
In this particular I try to delete the Food which the snake eats but nothing happens (Its marked in the Code), and the other function works just fine. I don't even get an Error.
If you need the other scripts, I can send those as well.
public void SnakeMoved(Vector2Int snakeGridPosition)
{
if (snakeGridPosition == foodGridPosition)
{
Object.Destroy(foodGameObject);
SpawnFood();
}
}
I tried to see if the rest in the IF clause works and the rest is working perfectly. I don't know what I did wrong.
Code for the foodGameObject:
private void SpawnFood()
{
foodGridPosition = new Vector2Int(Random.Range(0, width), Random.Range(0, height));
GameObject foodGameObject = new GameObject("Food", typeof(SpriteRenderer));
foodGameObject.GetComponent<SpriteRenderer>().sprite = GameAssets.i.foodSprite;
foodGameObject.transform.position = new Vector3(foodGridPosition.x, foodGridPosition.y);
}
In Unity you cannot create game objects in code using new GameObject(...). Instead you need to instantiate these, like that:
GameObject instantiatedFood = Instantiate(new GameObject("Food", typeof(SpriteRenderer)));
Instead of new GameObject("Food", typeof(SpriteRenderer)) you could also pass a prefab here which you link in the editor.
This instantiation step makes sense because you can prepare and deal with GameObjects in code before actually spawning them in the world.
I'm attempting to make a level select that requires as little upkeep as possible as I intend on adding updates to add more levels (Unity Scenes) in unity.
To account for this I'm attempting to get the level select to create buttons for each level in the Unity Build settings, and then create a template object from a prefab in which it can map buttons it creates onto.
I have it mostly working, but for some reason, it's mapping the buttons in the wrong order, I'm trying to go down to up and Unity appears to be grabbing the Gameobjects is a random order.
Here is my code:
private Scene[] levels;
private int currentButtonId = 1;
public Transform buttonsHolder;
public GameObject buttonPrefab;
public GameObject buttonSlotsPrefab;
private GameObject[] levelButtonSlots;
private int currentLevelSlot = 0;
private int numSlotsToMove = 0;
private void Start()
{
var sceneCount = SceneManager.sceneCountInBuildSettings;
levels = new Scene[sceneCount];
for (var i = 0; i < sceneCount; i++)
{
// Beginning Setup
levels[i] = SceneManager.GetSceneByBuildIndex(i);
// Look for Level Placement Slots
levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot");
// If there aren't enough Level Placement Slots make more by creating a template
if(levelButtonSlots.Length < levels.Length)
{
GameObject buttonSlots = Instantiate(buttonSlotsPrefab);
buttonSlots.transform.position = new Vector2(0, 10 * numSlotsToMove);
numSlotsToMove++;
}
// Go get those new placement slots
levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot");
// Create Button
GameObject currentButton = Instantiate(buttonPrefab, buttonsHolder);
// Move it to the next slot
currentButton.transform.position = levelButtonSlots[currentLevelSlot].transform.position;
currentLevelSlot++;
// Add Text to a new button
TextMeshProUGUI buttonText = currentButton.GetComponentInChildren<TextMeshProUGUI>();
buttonText.text = (currentButtonId.ToString());
// Setup what which scene clicking a button will do
ButtonManager buttonScript = currentButton.GetComponentInChildren<ButtonManager>();
buttonScript.sceneToLoad = currentButtonId;
currentButtonId++;
}
}
The buttonsHolder variable is set in the editor and is the canvas.
The buttonPrefab is a TextMeshPro button prefab I set in the editor, it has the level Buttons tag and a simple script that loads the specified scene when clicked.
And the buttonSlotsPrefab is a gameobject prefab that I set in the editor, it has the Button Placement Slot tag and it contains 8 other empty gameobjects each with the level slot tag, I use these 8 objects as the guides as to where the buttons should be placed on runtime.
Again, my goal is to place the buttons going from bottom to top, but instead, Unity spits out this on runtime for no apparent reason:
I'm sorry about the naming convention some variables have, I'm tired and stressed as I've been at this 2 two days straight. I will fix those up once I get things working.
After further testing, I have noticed that when I first create buttonSlotPrefab, everything works perfectly, however, after restarting Unity (Not changing any files) when I run the game again after a restart the order gets randomized. Could this be a bug in the Unity Engine?
If i understant your problem, you have a problem between number of button and slot: you have slot spaced on axis y and you havent always the levelsolt[0] at the bottom of screen, so
you could order (ascending or descending i dunno) the levelslot on y axis before creating button: i am using Linq so add using System.Linq;
if (levelButtonSlots.Any())//Same thing than levelButtonSlots.Length > 0
{
levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot").OrderBy(go => go.transform.position.y).ToArray();
}
or
levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot").OrderByDescending(go => go.transform.position.y).ToArray();
I have added a test if no value in array, but maybe the error doesnt exist, i havent tested that
I'm doing a platformer game with Unity 2D and I wanted to flip the character sprite left when the player move him left, but for some reasons it doesn't work. I tried to make this one script:
transform.rotation = new Vector3(0f, 180f, 0f);
but it didn't work. So then I wrote this:
transform.localScale = new Vector3(-0.35f, 0.35f, 1f); //the player's scale x and y are 0.35 by default
but it didn't work too. Then I found this error message in the console: NullReferenceException: Object reference not set to an instance of an object
UnityEditor.Graphs.Edge.WakeUp () (at C:/buildslave/unity/build/Editor/Graphs/UnityEditor.Graphs/Edge.cs:114).
What should I do? I'm doing this game for a game jam so I need to resolve this problem quickly. Thank you.
EDIT: I noticed that I can flip the sprite in the editor, but that I can't do that using scripts.
From this thread I found, it seems like an old bug from Unity's UnityEditor.Graphs.DLL code.
Try restarting Unity completely.
This bug seems to occur only in the editor, and not after a game is built, so you should be safe.
I haven't worked on any 2D Unity projects in a while but here is a piece of code I used to resolve that issue in the past. Let me know if it helps.
private void FlipSprite()
{
bool playerHasHorizontalSpeed = Mathf.Abs(myRigidBody.velocity.x) > Mathf.Epsilon;
if(playerHasHorizontalSpeed)
{
transform.localScale = new Vector2(Mathf.Sign(myRigidBody.velocity.x), 1f);
}
}
This is a bit old so be sure to let me know how this works. You'll need to finish the rest of the controls, but this should work.
public class SpriteFlipper : MonoBehaviour
{
// variable to hold a reference to our SpriteRenderer component
private SpriteRenderer mySpriteRenderer;
// This function is called just one time by Unity the moment the component loads
private void Awake()
{
// get a reference to the SpriteRenderer component on this gameObject
mySpriteRenderer = GetComponent<SpriteRenderer>();
}
// This function is called by Unity every frame the component is enabled
private void Update()
{
// if the A key was pressed this frame
if(Input.GetKeyDown(KeyCode.A))
{
// if the variable isn't empty (we have a reference to our SpriteRenderer
if(mySpriteRenderer != null)
{
// flip the sprite
mySpriteRenderer.flipX = true;
}
}
}
}
Hi I'm upgrade my unity game project from UNITY4.7.2 to UNITY2019.1.7f1 everything WORK ON UNITY EDITOR(UNITY2019.1.7f1) but after I'm build project to iPhoneX game isn't work for some function eg.FindGameObjectWithTag, GetComponent I'm check in code and found getcomponent is not work at calling time
I'm already solved this by add spawnArea prefab to inspector and call them but for another function that use GetComponent still not work.
please anybody suggest me about problem whem we call getcomponent problem.
I'm looking around my code, unity console and search in google too, and assume FindGameObjectWithTag, GetComponent and another code kind like those 2 have problem when upgrade unity4 to unity2019:
spawnPoint = GameObject.FindGameObjectWithTag(TagManager.spawnArea).transform;
if (currentVehicle != null) {
if(bigTruck)
DestroyImmediate(currentVehicle.transform.parent.gameObject);
else
DestroyImmediate(currentVehicle.gameObject);
}
GameObject vehicle = Instantiate(vehiclePrefabs[GameManager.instance.selectedCar], spawnPoint.position, spawnPoint.rotation) as GameObject;
currentVehicle = vehicle.GetComponent<BaseVehicle>();
if (currentVehicle == null) {
currentVehicle = vehicle.GetComponentInChildren<BaseVehicle>();
bigTruck = true;
} else {
bigTruck = false;
}
playerCamera.target = currentVehicle.transform;
playerCamera.vehicleFront = currentVehicle.transform.Find("Front");
In unity console when I use debug build they show "NullReferenceException: Object reference not set to an instance of an object." but I'm look around my code and not found any object that null reference, I test by compare with null eg.
if (currentVehicle == null) {
Debug.Log("currentVehicle is null");
}
This is my script and I tried to make "" in case it's not one of the cases:
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Platform")
Debug.Log("Touching Platform");
else Debug.Log("");
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.name == "OnTop Detector")
{
Debug.Log("On Top of Platform");
GameObject findGo = GameObject.Find("ThirdPersonController");
GameObject findGo1 = GameObject.Find("Elevator");
findGo.transform.parent = findGo1.transform;
}
else Debug.Log("");
}
But this "" not working. It's not deleting the text from the console while the game is running. And also when i stop the game and running it again it keep showing the last text of the Debug.Log.
I want to clear it if none of the If's happen in my script.
I saw this answer:
Answer
But i'm not sure if this is what I need and how to use it. Make a new script ?
And also what about errors. If I clear the Log in the console it will delete also erorrs if there will be some ?
In this screenshot it's in state after I touched the platform and then moved away from it but the text still exist in the console log:
The Debug.ClearDeveloperConsole() function is used when you clear logs from an application that was built while Debug Build is enabled in your project. There is no official API for clearing the Editor log.
Most Editor functionality can be replicated with Reflection just like hiding Gizmos and toggling the Stats Panel. I was going to write one but found this one.
This should clear every log on the Console tab.
using System.Reflection;
public void ClearLog()
{
var assembly = Assembly.GetAssembly(typeof(UnityEditor.ActiveEditorTracker));
var type = assembly.GetType("UnityEditorInternal.LogEntries");
var method = type.GetMethod("Clear");
method.Invoke(new object(), null);
}
Now, you can call ClearLog(); in your else statements.
EDIT:
This has changed recently in about ~Unity 2017. Since it is done with reflection, I consider it to change again anytime if any class, variable or function used in this code is renamed by Unity. Below is the new way to do this:
public void ClearLog()
{
var assembly = Assembly.GetAssembly(typeof(UnityEditor.Editor));
var type = assembly.GetType("UnityEditor.LogEntries");
var method = type.GetMethod("Clear");
method.Invoke(new object(), null);
}
Note that the Debug Log is longer than just one line (you can see it by clicking on said line).
You can try to use Debug.ClearDeveloperConsole() and see what you get.