Cannot to delete the GameObject - list

I put the all GameObjects in scene under a list. the following is function used in the shelf.cs to delete the gameobjects. I assign the function to a button, so that it takes input value and find which Gameobject has lesser value than input. Then delete. The problem is whenever I click the button in the game preview, it won't delete the gameobjects. There are no warnings. I debug whether it receives all input, and it did. just not deleting the GameObjects.
Why?
public void Process(){
int user_apple,user_lemon,user_watermelon;
user_apple = int.Parse (input_apple.text);
user_lemon = int.Parse (input_lemon.text);
user_watermelon = int.Parse (input_watermelon.text);
Debug.Log (user_apple+" "+user_lemon+" "+user_watermelon);
for(int i = players.Count - 1; i >= 0; i--)
{ if(players[i].name == "Lemon")
{
if(players[i].GetComponent<Apple>().weight <= user_apple)
{ Debug.Log ("wat u want");
Destroy(players[i]);
}players.RemoveAt(i);
}
}
}
if i were to put it like this,
public void Process(){
int user_apple,user_lemon,user_watermelon;
user_apple = int.Parse (input_apple.text);
user_lemon = int.Parse (input_lemon.text);
user_watermelon = int.Parse (input_watermelon.text);
Debug.Log (user_apple+" "+user_lemon+" "+user_watermelon);
if(players[2].GetComponent<Lemon>().weight <= user_apple)
{ Destroy(players[2]);
players.RemoveAt(2);
}
}
it will have errors like below
FormatException: Input string was not in the correct format
System.Int32.Parse (System.String s) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Int32.cs:629)
Basket.Process () (at Assets/scripts/Basket.cs:77)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:110)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:575)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent.cs:717)
UnityEngine.Events.UnityEvent.Invoke () (at C:/BuildAgent/work/d63dfc6385190b60/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/UI/Core/Button.cs:36)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/UI/Core/Button.cs:45)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/BuildAgent/work/d63dfc6385190b60/Extensions/guisystem/guisystem/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()

This may not be the right solution try calling a co-routine from the Process Function and yield the loop so it runs everyframe.

Just to recap what Joe Blow said: there is no reason why this for loop should not work since it is totally independant of frames/time.
This little example works perfectly fine:
The script ScriptHolder is assigned to an empty gameobject (see screen below) and looks like this:
using UnityEngine;
using System.Collections.Generic;
public class ScriptHolder: MonoBehaviour
{
public List<GameObject> theGameObjects;
public void TheButtonFunction(int weight)
{
for(int i = theGameObjects.Count - 1; i >= 0; i--)
{
if(theGameObjects[i].GetComponent<TheObject>().objectWeight <= weight)
{
Destroy(theGameObjects[i]);
theGameObjects.RemoveAt(i);
}
}
}
}
All gameobjects were dragged into the public list.
The script for the gameobjects looks like this:
using UnityEngine;
using System.Collections;
public class TheObject : MonoBehaviour
{
public string objectName = "";
public int objectWeight = 0;
}
All GameObject_A are named A and have a weight of 10 (done in the inspector), GameObject_B are B with a weight of 15 and GameObject_C are C with a weight of 20. Columns are A to C from left to right.
The button calls the function from above with a value of 15.
When I click the button, the left and the middle columns of gameobjects are deleted from the scene and from the list - no problem whatsoever.

Related

How can I distinguish my characters in a vector? SFML 2.4.1

I am using push_back to add identical characters and for some reason these characters all have the same stats all the time.
Battle.cpp:
void Battle::InitalizeUser()
{
user.t_Pokemon.clear();
user.t_Item.clear();
user.currentPokemon_U = 0;
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uG5);
user.t_Pokemon.push_back(&uG5);
user.t_Item.push_back(&uI1);
user.t_Item.push_back(&uI2);
for (unsigned int i = 0; i < user.t_Pokemon.size(); i++)
{
user.t_Pokemon.at(i)->poke_health = 100;
user.t_Pokemon.at(i)->poke_isFainted = false;
}
assert(user.t_Pokemon.size() == 6);
assert(user.t_Item.size() == 2);
}
So if uF1 health is reduced all uF1 characters will suffer the same reduction, but I don't want all the others uF1 to suffer the reduction, I want to be able to distinguish them and have only one specific character affected.
How can I do that?
Pokemon.cpp:
void Pokemon::attackNormal(Pokemon * opponentPokemon)
{
opponentPokemon->poke_health = opponentPokemon->poke_health - 20;
opponentPokemon->changeIfFainted();
assert(opponentPokemon->poke_health <= 100 && opponentPokemon->poke_health >= 0);
}
Battle.h:
class Battle
{
private:
static Trainer user;
static Trainer ash;
static IntRect user_Rect;
static IntRect ash_Rect;
// User's pokemon
static Fire uF1;
static Water uW3;
static Grass uG5;
static Item uI1;
static Item uI2;
}
uF1 : Pokemon.h
class Fire : public Pokemon
{
public:
Fire();
Fire(string name);
virtual ~Fire();
void specialAttack(Pokemon * opponentPokemon);
void changeWeather();
void Draw(RenderWindow &window);
};
The problem is that your vector contains copies of a pointer what is not equivalent to having different copies of an actual object.
It seems that you are passing same pointers several times in order to achieve object copy which is not a case.
You should first declare all your objects and then add their addresses to the vector.
Additional note: you don't have to create a variable for every object you use. You could also create an array of objects.

Unit test just returns 1 result of 10 cases from loop

i am trying to get all 10 results of 10 cases from For loop. but when i run, it just returns for me the first result of the first time. any help for this condition, this is my whole code, it includes
2 files, i have tried many times to fix it.
//file BankAccount.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Bank //just want to demo this thing, it hasn't completed
{
namespace BankAccountNS
{
public class BankAccount
{
private double m_balance;
public BankAccount(double balance)
{
m_balance = balance;
}
public bool getMoney(double amount) //funtion get money from account
{
if (amount > m_balance || amount < 0) //check money
{
return false;
}
return true;
}
}
}
}
//file BankAccountTests.cs
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Bank.BankAccountNS;
namespace BankTest
{
[TestClass]
public class BankAccountTests
{
[TestMethod]
public void TestEveryDebit(BankAccount Ba) //test every case from TestAll
{
Assert.IsTrue(Ba.getMoney(24000));
}
[TestMethod]
public void TestAll() //create all cases
{
for(int i = 0; i < 10; i++)
{
BankAccount Ba = new BankAccount(23996 + i);
TestEveryDebit(Ba);
}
}
}
}
I'm not really clear on what your (attempted) loop asserts would be accomplishing, but the method getMoney seemingly has 2 (or 3) useful unit tests:
Is the amount greater than the balance I have? - return false
Is my account balance less than zero - return false
Is my amount less than or equal too my balance? - return true
In your current setup (if it were to work) you're simply testing getMoney is returning true for amounts even greater than the balance - this is incorrect and does not adhere to the logic you have coded too.
I see your unit tests looking like:
private double _balance = 50;
private BankAccount _unitTestObject;
[TestMethod]
public void getMoney_returnsFalseWithInsufficientFunts() //create all cases
{
_unitTestObject = new BankAccount(_balance );
var results = _unitTestObject.getMoney(_balance+1);
Assert.IsFalse(results);
}
[TestMethod]
public void getMoney_returnsFalseWhenAccountHasLessThanZero() //create all cases
{
_unitTestObject = new BankAccount(-1);
var results = _unitTestObject.getMoney(1);
Assert.IsFalse(results);
}
[TestMethod]
public void getMoney_returnsTrueWhenAccountSufficientBalance() //create all cases
{
_unitTestObject = new BankAccount(_balance);
var results = _unitTestObject.getMoney(_balance);
Assert.IsTrue(results);
}
As I stated in comments, MSTest can't do parameterized tests, and what it looks like you're attempting to do (assert specific logic 10 times) could be done like this:
[TestClass]
public class BankAccountTests
{
[TestMethod]
public void TestAll() //create all cases
{
for(int i = 0; i < 10; i++)
{
BankAccount Ba = new BankAccount(23996 + i);
TestEveryDebit(Ba);
}
}
private void TestEveryDebit(BankAccount Ba) //test every case from TestAll
{
Assert.IsTrue(Ba.getMoney(24000));
}
}
But the test TestAll will always fail, because at some point in your loop, you're going to be trying to take out more amount than you have balance.
When Asserting based on a loop, the "success or failure" of the test is based on the whole, not each individual assert. So even though a few runs of your loop will "pass", the test will fail as a whole.

How to handle and avoid Recursions

I'm using custom classes to manage a vending machine. I can't figure out why it keeps throwing a stack overflow error. There are two versions to my program, the first is a basic test to see whether the classes etc work, by pre-defining certain variables. The second version is what it should be like, where the variables in question can change each time the program is ran (depending on user input).
If anyone can suggest ways of avoiding this recursion, or stack overflow, I'd great. Below is the code for the three classes involved;
class Filling
{
protected:
vector<Filling*> selection;
string fillingChosen;
public:
virtual float cost()
{
return 0;
}
virtual ~Filling(void)
{
//needs to be virtual in order to ensure Condiment destructor is called via Beverage pointer
}
};
class CondimentDecorator : public Filling
{
public:
Filling* filling;
void addToPancake(Filling* customerFilling)
{
filling = customerFilling;
}
~CondimentDecorator(void)
{
delete filling;
}
};
class Frosted : public CondimentDecorator
{
float cost()
{ //ERROR IS HERE//
return (.3 + filling->cost());
}
};
Below is the code used to call the above 'cost' function;
void displayCost(Filling* selectedFilling)
{
cout << selectedFilling->cost() << endl;
}
Below is part of the code that initiates it all (main method);
Filling* currentPancake = NULL;
bool invalid = true;
do
{
int selection = makeSelectionScreen(money, currentStock, thisState);
invalid = false;
if (selection == 1)
{
currentPancake = new ChocolateFilling;
}
else if...
.
.
.
.
else
invalid = true;
} while (invalid);
bool makingSelection = true;
CondimentDecorator* currentCondiment = NULL;
do
{
int coatingSelection = makeCoatingSelectionScreen(money, currentStock, thisState);
if (coatingSelection == 1)
currentCondiment = new Frosted;
else if (coatingSelection == 2)...
.
.
.
else if (coatingSelection == 0)
makingSelection = false;
currentCondiment = thisSelection;
currentCondiment->addToPancake(currentPancake);
currentPancake = currentCondiment;
displayCost(currentPancake);
//Below is the code that DOES work, however it is merely meant to be a test. The
//above code is what is needed to work, however keeps causing stack overflows
//and I'm uncertain as to why one version works fine and the other doesn't
/*currentCondiment = new Frosted;
currentCondiment->addToPancake(currentPancake);
currentPancake = currentCondiment;
displayCost(currentPancake);
currentCondiment = new Wildlicious;
currentCondiment->addToPancake(currentPancake);
currentPancake = currentCondiment;
displayCost(currentPancake);*/
} while (makingSelection);
displayCost(currentPancake);
delete currentPancake;
The infinite recursion happens when you call displayCostwith a Frosted whose filling is a Frosted as well. And that happens right here:
currentCondiment->addToPancake(currentPancake);
currentPancake = currentCondiment;
displayCost(currentPancake);
You set the filling of currentCondiment to currentPancake, then call displayCost with currentCondiment.
In the process you also leak the memory that was originally assigned to currentPancake.
Btw currentCondiment = thisSelection; also leaks memory.
Idea: Use smart pointers like std::unique_ptr to get rid of the leaks.

Multiple objects ,Same constructor.Can one constructor access another constructor's variable values?

I am using NS2 to simulate a modified routing protocol. This is how it works in brief:
I create some nodes using a .tcl file. For every node, a routing agent is created by the following:
static class WFRPclass : public TclClass {
public:
WFRPclass() : TclClass("Agent/WFRP") {}
TclObject* create(int argc, const char*const* argv) {
assert(argc == 5);
return (new WFRP((nsaddr_t) Address::instance().str2addr(argv[4])));
}
} class_rtProtoWFRP;
The new WFRP(nsaddr_t) is the constructor. This is the constructor code:
WFRP::WFRP(nsaddr_t id) : Agent(PT_WFRP),bcnTimer(this), rtcTimer(this){
index = id;
seqno = 0;
dest=0;
rand=371+(id*2);
nod++;
printf("N (%.6f): Routing agent is initialized for node %d ,Random Number is %d\n", CURRENT_TIME, id,rand);
LIST_INIT(&rthead);
posx = 0;
posy = 0;
logtarget = 0;
ifqueue = 0;
}
The above code runs in a .cc file.Lot of packet forwarding functions are defined here,and every node that forwards a packet increases it seq no by one.
The constructor and it's class are defined in a .h file
The class in .h are as follows
class WFRP : public Agent {
friend class RouteCacheTimer;
public:
WFRP(nsaddr_t id);
.....
/lot of functions defined here
}
Can one constructor of the class say WFRP(5) [nsaddr_t are just simple int numbers,ranging from 0 to number of nodes I create.They are sequential]
Can WFRP(5) access WFRP(8)'s seqno? Both these constructors will increase the values seqno independently of each other, so can I?
EDIT
The code is used in NS2.It uses a combination of tcl(front end) and c++(back end).This statement in tcl
$ns at 1.0 "[$mnode_(0) set ragent_] sink"
shifts the control to this line of c++ code
if(strncasecmp(argv[1], "sink", 4) == 0) {
bcnTimer.handle((Event*) 0);
printf("N (%.6f): sink node is set to %d, start beaconing ,Random Number set to %d \n", CURRENT_TIME, index,rand);
return TCL_OK;
}
Notice in the tcl line it is [mnode_(0)]..so right now the control flow is in WFRP(0) i.e. nsaddr_t =0.
Can WFRP(0) access WFRP(5) variable values.
Apologies,if the question is unclear.

Strange errors: EXC_BAD_ACCESS in my class

Here is my code:
typedef struct TItemSelector{
ItemSelectFrame* pItems[2];
} SItemSelector;
class item {
public:
void expMethod();
SItemSelector itemSelector_;
UILayerButton* startBtn_;
};
void item::expMethod(){
startBtn_ = new UILayerButton();
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
startBtn_->callMethodA();
}
void UILayerButton::callMethodA()
{
this->callMethodB();
}
void UILayerButton::callMethodB()
{
}
On this->callMethodB();, a "EXC_BAD_ACCESS" occoured.
After that I found a work-around:
class item {
public:
void expMethod();
SItemSelector itemSelector_;
SItemSelector itemSelector2_; // work around
UILayerButton* startBtn_;
};
Then everything goes well... I just don't know what happened, but callMethodB() is just an empty method, there's nothing to do with it.
I'm using Apple LLVM 3.1, default setting.
UPDATE: Fixed my code.
In this code:
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
you are writing over the end of itemSelector_.pItems because pItems is an array of length 2 but you are writing 3 elements.
That then overwrites startBtn_ which happens to appear immediately after itemSelector_ in memory. And that explains the error when you subsequently read the now corrupted startBtn_.
Either change your loop termination test, or increase the length of pItems. I can't tell which one is the correct solution, but clearly you will know.