- Home /
RTS Style building help
I'm making an RTS game and I have a GUI that I click to buy a building and place it. I'm trying to figure out how I can make the building place under the ground then slowly come up while at the same time taking a little amount of resources until the building is built.
For some reason when trying to place it under the ground this code wont work:
Vector3 newpos = new Vector3 (currentBuilding.transform.localPosition.x, -currentBuilding.transform.localPosition.y ,currentBuilding.transform.localPosition.z);
currentBuilding.transform.localPosition = newpos;
As for taking the resources that's where I'm stuck, I know how to make it move up and take resources away at the same time using a while loop in an IEnumerator but how could I : Make it move up by a number of seconds, take a small amount of resources each second AND make the small amount it is taking equal the total price of the whole building by the time its done the number of seconds it took to build? Thanks any feedback is appreciated!
Answer by iwaldrop · Dec 16, 2016 at 07:47 AM
It's some pretty basic math for all of these things. Simply put you want to do the following:
Place the structure where it should be when completed
Determine the incremental cost and delta position of the structure (where it should start).
Start a loop for the desired period of time
Lerp between the start and end position of the structure
Reduce the resources by the incremental value
If you're visibly subtracting the cost over time then you'll need to also keep track of the funds available; otherwise it'll be possible to start building two things at the same time and end up in the negative.
To perform your loop I'd recommend either writing a helper function that'll do something over time, or using a library like DOTween. An example of a function to do arbitrary things over time would look like this:
public static IEnumerator DoSomething(float duration, Action<float> callback) {
float elapsed = 0;
while ((elapsed += Time.deltaTime) < duration) {
callback(elapsed / duration);
}
}
void Example() {
const float DURATION = 15;
const int TOTAL_COST = 250;
var incrementalCost = TOTAL_COST / DURATION;
var targetPosition = MagicStructureProperty.transform.position;
var startPosition = targetPosition - Vector3.up * 10;
StartCoroutine(DoSomething(DURATION, t => {
Wallet.balance -= incrementalCost;
MagicStructureProperty.transform.position = Vector3.Lerp(startPosition, targetPosition, t);
}));
}
Definitely not the most elegant solution, but that's how it's done at a very basic level. I just want to set you in the right direction. Enjoy!
As a matter of fact, my solution is seriously flawed because it ticks every frame rather than every second or whatever. But, again, I'm just trying to set you on the right path, and I'm too busy playing $$anonymous$$WO right now to fix it. :)
When dividing total cost by duration most times Ill probably get a float value so how would that transfer over into an int since I dont want decimal points in my resource values?
That's a good question. There seem to be several solutions. Sounds like the most trivial way is to round the incremental value down and then remove the remainder when you're done.
But this is actually a potentially complex thing where multiple transactions can be occurring at once; both spending and accumulating money. You'll have two main values; the cash in the bank at any given time and the value that is displayed.
Honestly, you should probably divorce the act of spending money incrementally from that of animating the building appearing. Ins$$anonymous$$d you probably just want to animate the displayed value of your resources when the value is changed.
Resource transaction occurred
Some update loop just increments the visible value toward the actual value by a max value per frame.
In this way you keep transactions simple, always know how much you have in the bank, and naturally aggregate the result of many transactions as the balance of resources.
This is what I got done today, it may not be the most optimized code but it works for now, what do you think? It does everything I need but I haven't added the amount the building has to move up and how it moves up yet.
public IEnumerator Timer()
{
float TimeSpent = 0;
if (currentBuilding.CompareTag ("HQ")) {
int CostPerSecond = Building.HQCost / Building.HQBuildTime;
bool BulldozerApprove = true; //Approved to build or not
bool Paused = false; //Does it have enough resources to build?
while (R$$anonymous$$.Plastic >= 0 && BulldozerApprove == true) {
yield return new WaitForSeconds (1);
if (TimeSpent < Building.HQBuildTime) {
if (R$$anonymous$$.Plastic > 0 && R$$anonymous$$.Plastic >= CostPerSecond) {
Paused = false;
if (Paused == false && (TimeSpent += 1) <= Building.HQBuildTime) {
R$$anonymous$$.Plastic -= CostPerSecond;
R$$anonymous$$.PlasticText.text = R$$anonymous$$.Plastic.ToString (); //The text equals the int value
}
} else {
//If resources are not greater than 0 pause building from moving
Paused = true;
}
} else {
//If done building, turn off
BulldozerApprove = false;
}
}
}
yield return null;
}
Answer by GrKl · Dec 16, 2016 at 07:44 AM
Seems to me you should replace
-currentBuilding.transform.localPosition.y
by -YourBuildingHeight. As your localPosition.y is probably = 0. So -localPosition.y is still =0.
As for your ressources:
Each second:
money -= totalBuildingPrice / totalBuildTime;
anyOtherResource -= totalRessourceForThisBuilding / totalBuildTime;
... Same for all ressources this building costs
Your answer
Follow this Question
Related Questions
using Tilemap for 3D RTS game 1 Answer
RTS building placement collision problem C# 1 Answer
I need help for my RTS Games! 0 Answers
How to make a grid and able to place buildings on? 0 Answers