Announcement

Collapse
No announcement yet.

Grabbing a simple bool variable from another actor

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Grabbing a simple bool variable from another actor

    Hi,

    Just wondering what a good way of getting this would be. Basically, I have an Actor class called Wall that reports back true when it has been hit, and saves it to a bool variable called PositiveHit. What I want to do is take that varibale and use it in an if statement in my main character file. I did some research and found a way to access the actor in another file, using an ActorIterator, however for some reason it only ever reports back one of my walls, rather than all of them. I also imagine I'll need to use casting for this, but I'm not entirely sure of what syntax I would need for it. Any help would be appreciated. Here is the relevant code:

    FirstPersonCharacter.cpp

    Code:
    bool AFirstPersonCharacter::GetHitBool() {
            for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt) {
                    Wall = *ActorIt;
                    AActor * WallHit = Wall;
                    GLog->Log(*WallHit->GetName()); //weird scenario - literally only mywall3 is being detected in the world at all times.
                    break;
            }
            PositiveHit = Wall->PositiveHit; 
            if (PositiveHit == true) {
                    return true;
            }
            else (PositiveHit == false); {
                    return false;
            };
    
    }
    
    
    bool HitBool = AFirstPersonCharacter::GetHitBool();
    if (HitBool == true) {
             VelocityMultiplier = BaseMomentum;
    }
    else (HitBool == false); {
             VelocityMultiplier = VelocityMultiplier * 1.0f;
    }
    if (HitBool == true) {
             HitBool = false;
    }
    Wall.cpp

    Code:
    void AWall::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
    {
            GLog->Log(*OtherActor->GetName());
            PositiveHit = true;
    }
    
    void AWall::Tick(float DeltaTime)
    {
           Super::Tick(DeltaTime);
           frames = frames + 1.0f; //this is setup to make sure the velocitymultiplier starts increasing again afterwards, as there was a bug where it would stay at base forever.
           if (fmod(frames, 30.f) == 0) {
                   PositiveHit = false;
           }
    }
    This code works perfectly for the one wall, but all the others just don't change the velocity after being hit.


    Please excuse me if I've posted wrongly, this is my first time on the forum haha

    Thanks in advance!

    #2
    Code:
    bool AFirstPersonCharacter::GetHitBool() {
    for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt) {
    Wall = *ActorIt;
    AActor* WallHit = Wall;
    GLog->Log(*WallHit->GetName()); //weird scenario - literally only mywall3 is being detected in the world at all times.
    break; // YOU BREAK THE LOOP IN THE FIRST ACTOR FOUND.
    }
    PositiveHit = Wall->PositiveHit;
    if (PositiveHit == true) {
    return true;
    }
    else (PositiveHit == false); { // WRONG ';' HERE.
    return false;
    }; // USELESS ';' HERE.
    
    }
    
    
    bool HitBool = AFirstPersonCharacter::GetHitBool();
    if (HitBool == true) {
    VelocityMultiplier = BaseMomentum;
    }
    else (HitBool == false); { // WRONG ';' HERE.
    VelocityMultiplier = VelocityMultiplier * 1.0f;
    }
    if (HitBool == true) {
    HitBool = false;
    }

    Comment


      #3
      thank you, I'll give it a go later. - appreciate it!

      Comment


        #4
        The first thing that is realy bad about this, is that you iterate all walls.
        A better way of doing this is passing the attacker with the attack. The default projectile class has the "instigator" attribute for that. So the wall, when hit, can cast the "instigator" to the player and call a function on him.
        NodePrefabs | PluginBuilder | NotificationBackbone | WidgetBox | DebugWidget

        Comment


          #5
          Originally posted by SolidSk View Post
          Code:
          bool AFirstPersonCharacter::GetHitBool() {
          for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt) {
          Wall = *ActorIt;
          AActor* WallHit = Wall;
          GLog->Log(*WallHit->GetName()); //weird scenario - literally only mywall3 is being detected in the world at all times.
          break; // YOU BREAK THE LOOP IN THE FIRST ACTOR FOUND.
          }
          PositiveHit = Wall->PositiveHit;
          if (PositiveHit == true) {
          return true;
          }
          else (PositiveHit == false); { // WRONG ';' HERE.
          return false;
          }; // USELESS ';' HERE.
          
          }
          
          
          bool HitBool = AFirstPersonCharacter::GetHitBool();
          if (HitBool == true) {
          VelocityMultiplier = BaseMomentum;
          }
          else (HitBool == false); { // WRONG ';' HERE.
          VelocityMultiplier = VelocityMultiplier * 1.0f;
          }
          if (HitBool == true) {
          HitBool = false;
          }
          That does fix the issue of not going through every actor, however now the issue is that the boolean value cannot be read from Wall. I'm assuming it just isn't actually returning the actor from the loop now that I removed break;, but I can't think of a way to get them both to work fine

          Comment


            #6
            Originally posted by Rumbleball View Post
            The first thing that is realy bad about this, is that you iterate all walls.
            A better way of doing this is passing the attacker with the attack. The default projectile class has the "instigator" attribute for that. So the wall, when hit, can cast the "instigator" to the player and call a function on him.
            I don't doubt that my code is inefficient, but it would probably mean rewriting most of my logic if that was the case. I'm also not entirely certain what you mean by that, I'm quite a begininner relatively speaking.

            Comment


              #7
              Originally posted by ArcticRapidzzz View Post

              That does fix the issue of not going through every actor, however now the issue is that the boolean value cannot be read from Wall. I'm assuming it just isn't actually returning the actor from the loop now that I removed break;, but I can't think of a way to get them both to work fine
              You need to re-think your entire logic. Just removing the break will not fix the issue for you as the code after the for loop will run only for the last actor of the loop - and removing the break it was running only for the first as pointed out. If you put the code inside the loop it will not fix either as it will return right after checking the very first actor.

              Comment


                #8
                Originally posted by _brunocoimbra View Post

                You need to re-think your entire logic. Just removing the break will not fix the issue for you as the code after the for loop will run only for the last actor of the loop - and removing the break it was running only for the first as pointed out. If you put the code inside the loop it will not fix either as it will return right after checking the very first actor.
                Gotcha, guess I'll get started then hahaha

                Comment


                  #9
                  Just in case anyone is wondering, I managed to get it sorted. So just incase anyone wants to follow my probably incredibly inefficient solution here is the code!

                  Code:
                  bool AFirstPersonCharacter::GetHitBool() {
                           TArray<AWall*> Walls;
                           for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt) {
                                   Wall = *ActorIt; //adds the actor for the wall in this iteration to Wall
                                   Walls.Add(Wall); //adds the wall to the Walls array
                                   int WallsSize = Walls.Num();
                                   if (WallsSize == WallCount) { //compares the amount of walls added to total walls in scene , 6 atm, defined in the editor
                                           break; //goes into while loop
                                   } 
                            } //array of all wall actors in scene should be built now
                            int index = 0;
                            result = false; //resets result to false
                            while (index<WallCount) { //while there are still walls left to check
                                      PositiveHit = Walls[index]->PositiveHit; //grabs the bool for that wall
                                      if (PositiveHit == true) {
                                              result = true;
                                              break; //returns result, and empties the array again ready for the next loop
                                      }
                                      index = index + 1; //gets ready for the next wall
                             }
                             Walls.Empty();
                             return result;
                  
                  }

                  Comment


                    #10
                    Originally posted by ArcticRapidzzz View Post
                    Just in case anyone is wondering, I managed to get it sorted. So just incase anyone wants to follow my probably incredibly inefficient solution here is the code!

                    Code:
                    bool AFirstPersonCharacter::GetHitBool() {
                    TArray<AWall*> Walls;
                    for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt) {
                    Wall = *ActorIt; //adds the actor for the wall in this iteration to Wall
                    Walls.Add(Wall); //adds the wall to the Walls array
                    int WallsSize = Walls.Num();
                    if (WallsSize == WallCount) { //compares the amount of walls added to total walls in scene , 6 atm, defined in the editor
                    break; //goes into while loop
                    }
                    } //array of all wall actors in scene should be built now
                    int index = 0;
                    result = false; //resets result to false
                    while (index<WallCount) { //while there are still walls left to check
                    PositiveHit = Walls[index]->PositiveHit; //grabs the bool for that wall
                    if (PositiveHit == true) {
                    result = true;
                    break; //returns result, and empties the array again ready for the next loop
                    }
                    index = index + 1; //gets ready for the next wall
                    }
                    Walls.Empty();
                    return result;
                    
                    }
                    If you plan to do a project that is more then a week, seriously take a break and do some coding practice.
                    E.,g. https://www.codewars.com/ They give you a task and you have to write a function for it. You can look at the code of others to see how they solved the exact same problem.

                    As far as I can tell you want to do something if ANY wall was hit:
                    Code:
                    bool AFirstPersonCharacter::WasWallHit()
                    {
                       bool Result = false;
                       for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt)
                       {
                          Result |= (*ActorIt)->PositiveHit; // Result will always be true if it was true once
                          (*ActorIt)->PositiveHit = false; // Need to reset the hit
                       }
                       return Result;
                    }
                    P.S. can Unreal please finally stop fu**** up the forum?
                    Last edited by Rumbleball; 01-14-2021, 02:04 PM.
                    NodePrefabs | PluginBuilder | NotificationBackbone | WidgetBox | DebugWidget

                    Comment


                      #11
                      Originally posted by Rumbleball View Post

                      If you plan to do a project that is more then a week, seriously take a break and do some coding practice.
                      E.,g. https://www.codewars.com/ They give you a task and you have to write a function for it. You can look at the code of others to see how they solved the exact same problem.

                      As far as I can tell you want to do something if ANY wall was hit:
                      Code:
                      bool AFirstPersonCharacter::WasWallHit()
                      {
                      bool Result = false;
                      for (TActorIterator<AWall> ActorIt(GetWorld()); ActorIt; ++ActorIt)
                      {
                      Result |= (*ActorIt)->PositiveHit; // Result will always be true if it was true once
                      (*ActorIt)->PositiveHit = false; // Need to reset the hit
                      }
                      return Result;
                      }
                      P.S. can Unreal please finally stop fu**** up the forum?
                      thanks a bunch for the recommendation, I'll be sure to follow up on it! This project is what I'm working on for my coursework in my computer science class, hence why I'm just wanting to get it done rather than perfect it at this stage. (Not long left before it needs submitting) I had never delved into unreal before starting it, so I've been learning along the way.

                      Hey, I'll get a higher grade for improving the code after doing those challenges you suggested! But yeah, I'm definitely gonna have to do some intense practice before I head off to university this autumn Haha.

                      Comment

                      Working...
                      X