Inconsistent function call in C# - Unity 3D - c#

I'm running these functions on an update loop. The first Debug.Log() prints 2 values, the second Debug.Log() prints two different values. How is this possible if one function is calling the other?
private void Blend(Pose pose) {
Debug.Log(pose.name);
// reset previous animation
unBlend(previousPose);
// queue new pose
BlendQ.Enqueue(pose);
}
private void unBlend(Pose pose) {
Debug.Log(pose.name);
// only unblend if new pose is different
//if (pose.name == previousPose.name) return;
if (!running2) {
running2 = true;
StartCoroutine(IRun2(pose.name, pose.curve, pose.blendSpeed));
}
}
public class Pose {
public string name;
public float blendSpeed;
public AnimationCurve curve;
public Pose(string name, AnimationCurve curve, float blendSpeed) {
this.name = name;
this.curve = curve;
this.blendSpeed = blendSpeed;
}
}

Related

Try to display a int through a static field, but return a weird value (C#)

I'm trying to cut down on how much duplication I have on my code, so I decided to make one of my classes a static class since I decided that its data should really be shared with everyone. Here's the static method below:
// A static class, that holds all object's coordinates, and methods to return & update their values.
internal static class Coordinate
{
private static int[,] PlayerCoordinate { get; set; }
public static int[,] GateCoordinate { get; }
public static int[,] FountainCoordinate { get; }
static Coordinate() // FIRST VALUE IS X (column), SECOND VALUE IS Y (row).
{
PlayerCoordinate = new int[,] { { 0, 0 } };
GateCoordinate = PlayerCoordinate; // Just starts off in the same place as player.
FountainCoordinate = new int[,] { { 2, 0 } };
}
// A static method, that sends the data of all object coordinates, deconstructed into seperate ints.
public static int PlayerColumn() { return PlayerCoordinate[0, 0]; }
public static int PlayerRow() { return PlayerCoordinate[0, 1]; }
public static int GateColumn() { return GateCoordinate[0, 0]; }
public static int GateRow() { return GateCoordinate[0, 1]; }
public static int FountainColumn() { return FountainCoordinate[0, 0]; }
public static int FountainRow() { return FountainCoordinate[0, 1]; }
// Updates the coordinates of the player.
public static void UpdatePlayerCoordinate(int column, int row) { PlayerCoordinate = new int[,] { { column, row } }; }
}
The main issue comes in from my GameManager class. On the console, the beginning section should print out "You are the room at (Column=0, Row=0), but it prints this instead:
Here is the code for my GameManager class:
internal class GameManager
{
private bool IsGameOver;
private Player Player;
private Updater Updater;
// Don't need to call Fountain or Coordinate since they're static
public GameManager()
{
IsGameOver = false;
Player = new();
Updater = new();
}
public void RunGame()
{
while (!IsGameOver)
{
Console.WriteLine("----------------------------------------------------------");
Updater.DisplayPlayerPosition(); // This is the main line that I'm having issues with as of right now. All other functions past this are another problem.
Updater.DisplayPlayerSenses();
string playerInput = Player.GetInput();
Updater.MovePlayer(playerInput);
IsGameOver = Updater.CheckForWin();
}
}
}
And just to make sure, here is the code from my updater class, with the specific method that I'm having issues with:
internal class Updater
{
// No fields
// Default constructor
// Gets the text to show the player his current position.
public void DisplayPlayerPosition() // This is the method that I'm having issues with.
{
Console.WriteLine($"You are in the room at (Column={Coordinate.PlayerColumn}, Row={Coordinate.PlayerRow})");
}
...
I'm fairly new to the static keyword so I believe that I may be missing smth. I personally believe that it's because the class itself hasn't been initialized (like I haven't called the constructor for the Coordinate class, and apparently you can't call a static constructor anyways), but that's just me. If I could get any help, I'd greatly appreciate it!
PlayerColumn() and PlayerRow() are methods, but you are accesing them in the WriteLine statement as if they are properties.
Update your WriteLine to:
Console.WriteLine($"You are in the room at (Column={Coordinate.PlayerColumn()}, Row={Coordinate.PlayerRow()})");

How to setup undo/redo system during runtime with Unity3D

I'm trying to set up an undo/redo system during runtime and couldn't get my code to work correctly. I have created an undo button, but when I moved my game object and press the undo button, the game object doesn't go back to its original states.
I just wanted to be able to have the end-user undo /redo his lastest action during runtime and not during Editor mode. I have made several attempts and have tried many different scripts but haven't made any progress. Any suggestions?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class undoit : MonoBehaviour
{
public class setting
{
public GameObject Obj;
public Vector3 Pos;
public Quaternion Rot;
public bool Deleted;
public void Restore()
{
Obj.transform.position = Pos;
Obj.transform.rotation = Rot;
Obj.SetActive(Deleted);
}
public setting(GameObject g)
{
Obj = g;
Pos = g.transform.position;
Rot = g.transform.rotation;
Deleted = g.activeSelf;
}
}
public List<setting> UndoList;
public void AddUndo(GameObject g)
{
setting s = new setting(g);
UndoList.Add(s);
}
public void Undo()
{
if (UndoList.Count > 0)
{
UndoList[UndoList.Count - 1].Restore();
UndoList.RemoveAt(UndoList.Count - 1);
}
}
void Start()
{
UndoList = new List<setting>();
}
}
First you need something you can store the relevant data to like e.g.
public struct ObjectState
{
// The transform this data belongs to
private Transform transform;
private Vector3 localPosition;
private Quaternion localRotation;
private Vector3 localScale;
private bool active;
public ObjectState (GameObject obj)
{
transform = obj.transform;
localPosition = transform.localPosition;
localRotation = transform.localRotation;
localScale = transform.localScale;
active = obj.activeSelf;
}
public void Apply()
{
transform.localPosition = localPosition;
transform.localRotation = localRotation;
transform.localScale = localScale;
transform.gameObject.SetActive(active);
}
}
Next I would use a wrapper class to store undo able changes like
public struct UndoableChange
{
private ObjectState _before;
private ObjectState _after;
public UndoableChange (ObjectState before, ObjectState after)
{
_before = before;
_after = after;
}
public void Undo()
{
_before.Apply();
}
public void Redo()
{
_after.Apply();
}
}
Or in case you need it for my objects at once you could use lists e.g. something like
public struct UndoableChange
{
private List<ObjectState> _before;
private List<ObjectState> _after;
public UndoableChange (List<ObjectState> before, List<ObjectState> after)
{
_before = before;
_after = after;
}
public void Undo()
{
foreach(var state in _before)
{
state.Apply();
}
}
public void Redo()
{
foreach(var state in _after)
{
state.Apply();
}
}
}
Then for the controller I would use two Stack. A Stack is "last in - first out" so exactly what you need. You add new entries using Push and by using Pop you retrieve the last added element and at the same time remove it from the stack. So it would look like
public static class UndoRedo
{
private static Stack<UndoableChange> undoStack = new Stack<UndoableChange>();
private static Stack<UndoableChange> redoStack = new Stack<UndoableChange>();
public static void Undo()
{
if(undoStack.Count == 0) return;
var lastAction = undoStack.Pop();
lastAction.Undo();
redoStack.Push(lastAction);
}
public static void Redo()
{
if(redoStack.Count == 0) return;
var lastAction = redoStack.Pop();
lastAction.Redo();
undoStack.Push(lastAction);
}
public static void AddAction(UndoableChange action)
{
redoStack.Clear();
undoStack.Push(action);
}
}
I dont know how exactly your user interacts with the objects but you now would always do something like
// at some point store the initial values
var before = new ObjectState (selectedGameObject);
//TODO Apply all your changes to the selected object
// get the new values
var after = new ObjectState (selectedGameObject);
// Log to the history
UndoRedo.AddAction(new UndoableChange(before, after));
or use lists for all selected objects accordingly e.g. simply using Linq
using System.Linq;
...
var before = selectedGameObjects.Select(obj => new ObjectState(obj)).ToList();
//TODO Apply all your changes to all the selected objects
var after = selectedGameObjects.Select(obj => new ObjectState(obj)).ToList();
UndoRedo.AddAction(new UndoableChange(before, after));
Note: Typed on smartphone but I hope the idea gets clear

Assigning Custom AABB To game objects

I'm trying to set up custom mathematic code in my Unity project to test for collision using AABB.
So far, I'm pretty sure I have the code just to calculate if two boxes are colliding, but not sure how I'd essentially attach them to a game object to test if they are colliding.
Here's the code I have currently.
The LineIntersection and IntersectingAxis functions can be ignored I believe, it's just part of my class.
public class AABB
{
public AABB(Vector3 Min, Vector3 Max)
{
MinExtent = Min;
MaxExtent = Max;
}
//This could be a Vector2 if you want to do 2D Bounding Boxes
Vector3 MinExtent;
Vector3 MaxExtent;
public float Top
{
get { return MaxExtent.y; }
}
public float Bottom
{
get { return MinExtent.y; }
}
public float Left
{
get { return MinExtent.x; }
}
public float Right
{
get { return MaxExtent.x; }
}
public float Front
{
get { return MaxExtent.z; }
}
public float Back
{
get { return MinExtent.z; }
}
public static bool Intersects(AABB Box1, AABB Box2)
{
return !(Box2.Left > Box1.Right
|| Box2.Right < Box1.Left
|| Box2.Top < Box1.Bottom
|| Box2.Bottom > Box1.Top
|| Box2.Back > Box1.Front
|| Box2.Front < Box1.Back);
}
}
And in another script called AABBCollider I have the following code
[RequireComponent(typeof(MatrixController))]
public class AABBCollider : MonoBehaviour {
private MatrixController MCCache;
public Vector3 CubeSize = new Vector3(1,1,1);
public VectorAlgorithm.AABB aabb;
public VectorAlgorithm.AABB aabb2;
//public VectorAlgorithm.AABB other;
public bool Intersect(AABBCollider other)
{
return VectorAlgorithm.AABB.Intersects(aabb, other.aabb);
}
// Use this for initialization
void Start () {
MCCache = GetComponent<MatrixController>();
//aabb = new VectorAlgorithm.AABB(MCCache.position - CubeSize, MCCache.position + CubeSize);
}
// Update is called once per frame
void Update () {
aabb = new VectorAlgorithm.AABB(MCCache.position - CubeSize, MCCache.position + CubeSize);
Debug.Log(VectorAlgorithm.AABB.Intersects(aabb, aabb));
}
}
The AABBCollider Script it attached to my 'PlayerCharacter' and 'Enemy' game objects. All I'm trying to do is print to the console either true or false if they are colliding or not.
I'm pretty sure aabb is 'attached???' to one game object, so doing (aabb, aabb) just returns true, which I'm not after.
If they collide, print TRUE to the console, if they're not colliding, print FALSE to the console.
At this stage, I'm not too worried about pushing them apart if they collide, just want to know my function is working.

C# way of telling how many enemies alive

I have my base game class and an enemy class.
When I instantiate an enemy using the base game I would like a integer to increase
And when one dies I would need it to decrease the integer.
The end result being a new enemy spawns every few seconds so long as that integer is less than my MAX_ENEMIES
any way I'm currently clue less and was hoping someone could direct me with how I should arrange this ( do I have the enemies increase the number when they spawn? )
Here's the basic idea: use a Factory Method. You may want to handle some of the specifics differently.
void Main()
{
var game = new Game();
game.CreateEnemy("Blinky");
Console.WriteLine(game.EnemyCount);
game.CreateEnemy("Clyde");
Console.WriteLine(game.EnemyCount);
game.DestroyEnemy(game.Enemies[0]);
Console.WriteLine(game.EnemyCount);
}
public class Game
{
public List<Enemy> Enemies = new List<Enemy>();
public void CreateEnemy(string name)
{
if (EnemyCount >= MAX_ENEMIES) return;
var enemy = new Enemy { Name = name};
Enemies.Add(enemy);
}
public void DestroyEnemy(Enemy enemy)
{
Enemies.Remove(enemy);
}
public int EnemyCount
{
get { return Enemies.Count(); }
}
}
public class Enemy
{
public string Name { get; set; }
}

Unity. Function call after a certain period of time

How can I make an object invisible (or just delete) after a certain period of time?
Use NGUI.
My example (for changes):
public class scriptFlashingPressStart : MonoBehaviour
{
public GameObject off_Logo;
public float dead_logo = 1.5f;
void OffLogo()
{
off_Logo.SetActive(false);
}
//function onclick button
//remove item after a certain time after pressing ???
void press_start()
{
InvokeRepeating("OffLogo", dead_logo , ...);
}
}
Use Invoke rather than InvokeRepeating.
check Invoke function here
public class scriptFlashingPressStart : MonoBehaviour
{
public GameObject off_Logo;
public float dead_logo = 1.5f;
bool pressed = false;
void OffLogo()
{
//do anything(delete or invisible)
off_Logo.SetActive(false);
pressed = false;
}
//use Invoke rather than InvokeRepeating
void press_start()
{
if(!pressed)
{
pressed = true;
Invoke("OffLogo", dead_logo);
}
else
{
Debug.Log("Button already pressed");
}
}
}
try
StartCoroutine(SomeFunctionAfterSomeTime);
IEnumerator SomeFunctionAfterSomeTime()
{
... //Your own logic
yield return new WaitForSeconds(SomeTime);
}
You can destroy an object in a given time by simply calling Destroy.
public static void Destroy(Object obj, float t = 0.0F);
Parameters
obj The object to destroy.
t The optional amount of time to delay
before destroying the object.
See http://docs.unity3d.com/Documentation/ScriptReference/Object.Destroy.html

Categories

Resources