So, the first part of my question is the primary reason I’m posting.
I’ve created a scene that, primarily, uses the following scripts
DialogueManager
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class DialogueManager : MonoBehaviour {
public GameObject NPCWindow;
public Text NPCText;
public GameObject responseBox;
public Button[] responseButtons;
public Text[] responseText;
//public CharacterController thePlayer;
public string[] NPCLines;
public string[] responses;
public string clickedButton;
public bool clicked;
public bool response;
public bool convoEnding;
public bool isActive;
public int currentLine;
public int endLine;
void Start () {
//thePlayer = FindObjectOfType<CharacterController>();
responseButtons = new Button[1];
responseButtons = GameObject.Find("Response").GetComponentsInChildren<Button>();
responseText = new Text[1];
responseText = GameObject.Find("Response").GetComponentsInChildren<Text>();
DisableButtons();
DisableNPCText();
}
void Update () {
if((Input.GetKeyDown(KeyCode.Return)) && (isActive == true))
{
currentLine += 1;
if((currentLine >= endLine) && convoEnding == true)
{
DisableNPCText();
}
else if((currentLine >= endLine) && convoEnding == false)
{
EnableButtons();
}
else
{
NPCDialogue(NPCLines[currentLine]);
}
}
if (response == true)
{
for (var i = 0; i < responses.Length; i++)
{
responseButtons[i].interactable = false;
}
}
}
public void NPCDialogue(string Text)
{
NPCText.text = "";
NPCText.text = Text;
}
public void DisableButtons()
{
responseBox.SetActive(false);
response = false;
}
public void EnableButtons()
{
responseBox.SetActive(true);
for(var i = 0; i < responseButtons.Length;i++)
{
if(responseText[i].text != "")
{
responseButtons[i].gameObject.SetActive(true);
responseButtons[i].interactable = true;
}
else
{
responseButtons[i].gameObject.SetActive(false);
}
}
}
public void DisableNPCText()
{
NPCWindow.SetActive(false);
isActive = false;
//thePlayer.canMove = true;
}
public void EnableText()
{
NPCWindow.SetActive(true);
isActive = true;
//thePlayer.canMove = false;
NPCDialogue(NPCLines[currentLine]);
}
}
I’ve commented out lines that only determine whether or not the player can move their character while the dialogue is open, and seems to have no affect on the crash.
SmallPlot
using UnityEngine;
public class SmallPlot : MonoBehaviour
{
public DialogueManager theManager;
private bool waitForPress;
public string currentConversation = "convoStart";
private string currentResponse;
private string[] NPCspeech;
private string[] responses;
private string input = "0";
public string currentBuild = "none";
public Transform building;
public Transform anchor;
public Transform placeHolder;
public Transform house;
void Start()
{
theManager = FindObjectOfType<DialogueManager>();
}
void Update()
{
if (waitForPress && Input.GetKeyDown(KeyCode.J))
{
Invoke(currentConversation, 0.1f);
}
if (theManager.response == true)
{
input = theManager.clickedButton;
Invoke(currentResponse, 0.1f);
}
}
public void convoStart()
{
input = "0";
NPCspeech = new string[2];
responses = new string[3];
NPCspeech[0] = "This is a small plot. The current structure is: " + currentBuild + ".";
NPCspeech[1] = "What would you like to do?";
responses[0] = "Build";
responses[1] = "Demolish";
responses[2] = "Leave";
sendUpdate();
currentResponse = "startResponses";
}
public void startResponses()
{
print("Response start");
switch (input)
{
case "Button1":
print("Response 1");
cleanUp();
if (currentBuild == "none")
{
NPCspeech = new string[2];
responses = new string[3];
NPCspeech[0] = "Construction? Splendid! Just what we need!";
NPCspeech[1] = "What would you like to build?";
responses[0] = "House";
responses[1] = "Go back";
responses[2] = "Nevermind";
theManager.convoEnding = false;
sendUpdate();
currentResponse = "build";
}
else
{
NPCspeech = new string[2];
responses = new string[3];
NPCspeech[0] = "This plot is not empty!";
NPCspeech[1] = "What would you like to do?";
responses[0] = "Build";
responses[1] = "Demolish";
responses[2] = "Leave";
theManager.convoEnding = false;
sendUpdate();
currentResponse = "startResponses";
}
break;
case "Button2":
print("Response 2");
cleanUp();
if(currentBuild == "none")
{
NPCspeech = new string[2];
responses = new string[3];
NPCspeech[0] = "There is nothing to demolish!";
NPCspeech[1] = "What would you like to do?";
responses[0] = "Build";
responses[1] = "Demolish";
responses[2] = "Leave";
theManager.convoEnding = false;
sendUpdate();
currentResponse = "startResponses";
}
else
{
NPCspeech = new string[2];
responses = new string[2];
NPCspeech[0] = "Are you sure you wish to demolish " + currentBuild + "?";
NPCspeech[1] = "This action is irrevereversble. Continue?";
responses[0] = "Yes";
responses[1] = "Cancel";
theManager.convoEnding = false;
sendUpdate();
currentResponse = "demolish";
}
break;
case "Button3":
print("Response 3");
cleanUp();
NPCspeech = new string[1];
NPCspeech[0] = "Farewell.";
theManager.convoEnding = true;
sendUpdate();
break;
}
}
public void build()
{
switch (input)
{
case "Button1":
cleanUp();
if (currentBuild == "none")
{
var currentStructure = this.gameObject.transform.FindChild(placeHolder.name).gameObject;
Destroy(currentStructure);
}
NPCspeech = new string[1];
NPCspeech[0] = "Constructing a house.";
var build = Instantiate(house, anchor.position, anchor.rotation) as Transform;
build.parent = this.transform;
build.name = house.name;
theManager.convoEnding = true;
sendUpdate();
currentBuild = "House";
building = build.transform;
break;
case "Button2":
cleanUp();
convoStart();
break;
case "Button3":
close();
break;
}
}
public void demolish()
{
switch (input)
{
case "Button1":
cleanUp();
NPCspeech = new string[1];
NPCspeech[0] = "Demolishing " + currentBuild + ".";
print(building.name);
var demolish = this.gameObject.transform.FindChild(building.name).gameObject;
Destroy(demolish);
var holder = Instantiate(placeHolder, anchor.position, anchor.rotation) as Transform;
holder.parent = this.transform;
holder.name = placeHolder.name;
theManager.convoEnding = true;
sendUpdate();
currentBuild = "none";
building = holder.transform;
break;
case "Button2":
cleanUp();
convoStart();
break;
}
}
public void close()
{
cleanUp();
NPCspeech = new string[1];
NPCspeech[0] = "Farewell.";
theManager.convoEnding = true;
sendUpdate();
}
public void sendUpdate()
{
theManager.NPCLines = NPCspeech;
theManager.endLine = NPCspeech.Length;
theManager.currentLine = 0;
theManager.EnableText();
for (var i = 0; i < responses.Length;)
{
theManager.responseText[i].text = "";
theManager.responseText[i].text = responses[i];
i += 1;
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
waitForPress = true;
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
waitForPress = false;
}
}
void cleanUp()
{
for (var i =0; i < theManager.responseButtons.Length; i++)
{
theManager.responseText[i].text = "";
}
input = "0";
theManager.DisableNPCText();
theManager.DisableButtons();
}
}
and, finally
ButtonID
using UnityEngine;
using System.Collections;
public class ButtonID : MonoBehaviour {
public DialogueManager theManager;
void Start()
{
theManager = FindObjectOfType<DialogueManager>();
}
public void isClicked()
{
print("Button pressed");
theManager.clickedButton = gameObject.name;
theManager.response = true;
print(gameObject.name+" Clicked");
}
}
DialogueManager is placed on an empty game object and, for the most part, finds the game objects/UI objects we’re looking for automatically. There are 2 panels, one displaying text (NPCWindow/NPCText) and 6 buttons in the other panel.
SmallPlot is placed on the object the player will be interacting with and will send things to DialogueManager to display, and read from DialogueManager which button has been pressed.
ButtonID is placed on all 6 of the buttons and tells the DialogueManager that a button has been pressed and which button it was.
The issue I’m running in to is that when you click on one of the buttons, it causes a crash-to-desktop. I was hoping this was fixed in the update, but seeing as it persists I’m thinking there might be something in my scripts that is causing the problem. I have no idea what it is, though, because one moment things will be working, then I’ll add some stuff to SmallPlot and then I’ll be getting the crashes that not even reverting back will fix.
The crash log I get is:
Crash
Unity Editor [version: Unity 5.3.2f1_e87ab445ead0]
Unity.exe caused an Access Violation (0xc0000005)
in module Unity.exe at 0033:4033e700.
Error occurred at 2016-01-30_040648.
E:\Programs\Unity\Editor\Unity.exe, run by Vedrit.
35% memory in use.
16322 MB physical memory [10596 MB free].
32706 MB paging file [26652 MB free].
134217728 MB user address space [134215921 MB free].
Read from location 00000000 caused an access violation.
Context:
RDI: 0x264bc478 RSI: 0x264bc900 RAX: 0x00000000
RBX: 0x25734e27 RCX: 0x264bc900 RDX: 0x0024e080
RIP: 0x4033e700 RBP: 0x0024e0e1 SegCs: 0x00000033
EFlags: 0x00010206 RSP: 0x0024e020 SegSs: 0x0000002b
R8: 0x00000000 R9: 0xffffffff R10: 0x00000000
R11: 0x0024dfe0 R12: 0x00000000 R13: 0x088ec8a0
R14: 0x40339850 R15: 0x0000018d
Bytes at CS:EIP:
0f b6 08 38 0b 0f 85 ee 01 00 00 48 8b cb 4c 8b
Stack:
0x0024e020: 0024e170 00000000 0024e1a0 00000000 p.$.......$.....
0x0024e030: 03273300 00000000 035e2b40 00000000 .3'.....@+^.....
0x0024e040: fffffffe ffffffff e39f844b 00007fff ........K.......
0x0024e050: 0024e0e0 00000000 40111867 00000001 ..$.....g..@....
0x0024e060: 264bc478 00000000 00000004 ffffffff x.K&............
0x0024e070: 0024e170 00000000 00000000 00000000 p.$.............
0x0024e080: 264bc8a0 00000000 26619500 00000000 ..K&......a&....
0x0024e090: fffff5f0 00000000 00000000 00000000 ................
0x0024e0a0: ffffffff ffffffff 00000000 00000000 ................
0x0024e0b0: 00000000 00000000 00000000 00000000 ................
0x0024e0c0: 00000000 00000000 00000000 00000000 ................
0x0024e0d0: 00000000 00000000 00000000 00000000 ................
0x0024e0e0: fffffffe ffffffff 00000000 00000000 ................
0x0024e0f0: 00000000 00000000 00000000 00000000 ................
0x0024e100: 00000000 00000000 00000000 00000000 ................
0x0024e110: e8a469fa 00005bf7 00000000 00000000 .i...[..........
0x0024e120: 264bc478 00000000 00000004 00000000 x.K&............
0x0024e130: 0024e2f0 00000000 4033acb2 00000001 ..$.......3@....
0x0024e140: 0024e1c0 00000000 00000000 00000000 ..$.............
0x0024e150: 00000000 00000000 00000000 00000000 ................
0x0024e160: 00000004 00000000 00000000 00000000 ................
0x0024e170: 00000000 00000000 00000000 00000000 ................
0x0024e180: 00000000 00000000 069146e0 00000000 .........F......
0x0024e190: 088ec8a0 00000000 4031a600 00000001 ..........1@....
I’ve submitted the bug report, but this portion of my project is a bit urgent, so I’m wanting some assistance a bit sooner than a response to the bug report (Previous submissions for this have gone un-answered)
On to the second and minor part (Really, if this part doesn’t get answered, I won’t be upset. I should probably ask on the SFS forums anyway). I’m using Smartfoxserver for my networking solution but I’m very dissatisfied in the level of detail in their documentation. Can someone explain how I might go about instantiating an object and have it propagate to all connected users?