x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How can i shoot at the center of my crosshair? C++

Hey! So, i'm getting in a little trouble in my shooting system. I did the Unreal tutorial (crosshair) to add a crosshair in the center of the screen. But when i'm shooting, is not going at the center. I know thats because have a difference between my weapon muzzle and my center of the camera. How can i setup that? so far, i have 2 line traces that i use for shooting (as usual).

 const FVector AimDir = WeaponMesh->GetSocketRotation("MF").Vector();
     const FVector StartTrace = WeaponMesh->GetSocketLocation("MF");
     const FVector ShootDir = AimDir;
     const FVector EndTrace = StartTrace + ShootDir * WeaponConfig.WeaponRange;
     const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
     const FRotator AimRot = WeaponMesh->GetSocketRotation("MF");
     const FVector EndPoint = Impact.GetActor() ? Impact.ImpactPoint : EndTrace;
 
     FActorSpawnParameters SpawnParams;
     SpawnParams.Owner = this;
     
     UWorld* World = GetWorld();
 
     AWeaponBullet* Projectile = World->SpawnActor<AWeaponBullet>(ProjectileClass, StartTrace, AimRot, SpawnParams);


How can i move my crosshair to my impact point? (I don't want change my shoot direction D:)

Product Version: UE 4.16
Tags:
ue4cro.jpg (149.3 kB)
more ▼

asked Oct 18 '17 at 08:45 PM in C++ Programming

avatar image

Varmillion
38 1 4 6

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

I'm not sure exactly how you want it to work, but if you don't want to change your shooting direction, you will have to constantly do a trace in your aim direction (this will get complicated if your projectile has gravity applied) until you find a hit, then reproject that world location back to the screen, get the 2D coordinates and draw your crosshair at that location. Be aware that your crosshair will jump around on the screen as you're effectively introducing a depth parameter. You can have a look at GameplayStatics::ProjectWorldToScreen(...).

Update: Here's some code.

 void APWNCharacter::TestShoot()
 {
     // Declare some required params
     const float traceDistance = 5000.f;
     const bool drawDebugLine = true;
     const float calibarionDistance = 3000.f;
     const float projectileSpeed = 4000.f;
 
     // Get ViewRotation & Viewpoint    
     // I don't know what your setup is but I'm using a custom camera. You require the current world rotation of the active camera. You could try "Cast<APlayerController>(Controller)->PlayerCameraManager->GetCameraRotation().Vector()"
     FVector viewDir = Camera->GetComponentRotation().Vector();
     viewDir.Normalize();
     // I don't know what your setup is. I'm using a custom camera, but you require the center of the screen's world location. You could try "Cast<APlayerController>(Controller)->PlayerCameraManager->GetCameraLocation();"
     FVector traceStart = Camera->GetComponentLocation();
     FVector traceEnd = traceStart + viewDir * traceDistance;
         
     // Set up trace params
     FCollisionQueryParams RV_TraceParams = FCollisionQueryParams(FName(TEXT("RV_Trace")), true, this);
     RV_TraceParams.bTraceComplex = true;
     RV_TraceParams.bTraceAsyncScene = true;
     RV_TraceParams.bReturnPhysicalMaterial = false;
     RV_TraceParams.AddIgnoredActor(this->GetUniqueID());
 
     //Re-initialize hit info
     FHitResult RV_Hit(ForceInit);
 
     // Trace from center of screen in direction of aim
     GetWorld()->LineTraceSingleByChannel(
         RV_Hit,        //result
         traceStart,    //start
         traceEnd, //end
         ECC_Visibility, //collision channel
         RV_TraceParams
     );
 
     // Requires include: #include "Runtime/Engine/Public/DrawDebugHelpers.h"
     if (drawDebugLine)
         DrawDebugLine(GetWorld(), traceStart, traceEnd, FColor::Green, true);
 
     // Get the muzzle location
     FVector muzzleLoc = CurrentWeapon->WeaponMesh->GetSocketLocation("MF");
 
     // The required direction of the projectile
     FVector locationToSendProjectileTo;
 
     // If we've hit something with the trace, let's send the projectile there.
     if (RV_Hit.bBlockingHit)
     {
         locationToSendProjectileTo = RV_Hit.ImpactPoint;
     }
     // Otherwise we use a "calibration distance". The distance from us at which the bullet should intersect the crosshair line
     else 
     {
         locationToSendProjectileTo = traceStart + viewDir * calibarionDistance;
     }
 
     // Calculate bullet velocity
     FVector bulletVelocity = locationToSendProjectileTo - muzzleLoc;
     bulletVelocity.Normalize();
     bulletVelocity *= projectileSpeed;
 
     // Draw debug line to show where bullet will go
     if (drawDebugLine)
         DrawDebugLine(GetWorld(), muzzleLoc, locationToSendProjectileTo, FColor::Red, true);
 
     // Spawn projectile at muzzle location and set its velocity...    
         ....
 }
more ▼

answered Oct 19 '17 at 02:38 PM

avatar image

staticvoidlol
2.6k 95 41 111

avatar image Varmillion Oct 19 '17 at 05:33 PM

Just need to be like that

Yeap, have gravity but the player have to handle this himself, i just need that my projectile (at least on the first seconds, before start losing altitude) goes on the center of the crosshair. I have made one using traces, but on traces, you can set the End.

avatar image staticvoidlol Oct 19 '17 at 06:06 PM

Ok - I think what's happening in that video is:

  • When shot is fired, trace from the center of screen in the camera view direction until the first hit is found

  • Spawn the projectile at the gun muzzle location

  • Calculate the projectile direction as the vector that would connect the gun muzzle and the hit location of the trace (HitLoc - MuzzleLoc)

The other possibility is:

  • Decide beforehand on a "calibration distance"

  • When shot is fired, find the point determined by moving from the center of the screen in the camera view direction for "calibration distance" units. Let's call this point "Calibration point".

  • Calculate the projectile direction as the vector that would connect gun muzzle and calibration point.

Which approach to follow depends on what you want the subtle behaviour to be, but neither of these retain the weapon model's "true aim direction".

avatar image staticvoidlol Oct 20 '17 at 01:30 AM

Not sure where my last comment went - I assume ColdSteel48 deleted their last comment and added a new one instead. In any case, the point is that you need 3 items:

  • The world location of where you want the projectile to go (constrained by the view/camera direction)

  • The muzzle location

  • The vector that connects these two points, which is the projectile velocity (after normalizing and applying the required velocity)

avatar image ColdSteel48 Oct 20 '17 at 01:32 AM

Yes I deleted em priorly to your post - realizing that same thing u posted now

avatar image ColdSteel48 Oct 20 '17 at 01:33 AM

Probably seeing the triangle in the picture killed my logic :-) though it would work, but extrimrly inefficient

avatar image ColdSteel48 Oct 19 '17 at 08:13 PM

Why not just to use deproject screen location to world - which will give the normalized direction angle - and then woalla you shoot at that angle ?

avatar image ColdSteel48 Oct 19 '17 at 08:18 PM

If you need a line trace then - use the deprojected point as a line trace start then use the direction vector miltiplied by a projectile max distance and add it to the deprojected point and you will get the line trace end point.

avatar image Varmillion Oct 19 '17 at 11:26 PM

Yes, all that i need is the rotation alt text

So, how can i get my "WorldLocation and WorldLocation"? I was looking for that function and discovered that uses your controller, but in the controller class "GetActorLocation or Rotation" are restrict.

loc.jpg (27.2 kB)
avatar image ColdSteel48 Oct 20 '17 at 12:46 AM

Oh now I see the whole problem :-). Use AHUD class to deproject the the position (center of the screen) to the world location and position (https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/AHUD/Deproject/index.html)

Then line trace from the deproject location lets call it A you will also get the direction from this function lets call it B.

Now you want to line trace from A to A + B * shoot range.
Now you want to shoot from Muzzle location to your destination location returned by a hit result.

To find the rotation: (Destination - muzzle) then normalize it and get rotation.

avatar image ColdSteel48 Oct 20 '17 at 01:25 AM

staticvoidlol Yes exactly, I overthink it a bit it's 4am though :-). your answer is correct - I just trying to explain it :-)

avatar image staticvoidlol Oct 20 '17 at 01:35 AM

Sure no worries :). Your comments did introduce me to the Deproject function on the HUD which seems very useful. I usually just think in simpler terms with simple steps because I can't keep it all in my head at once (need more RAM I think).

avatar image ColdSteel48 Oct 20 '17 at 01:38 AM

And I found it as an interesting question as well, since I never made a shooter game :-) Didn't even know such problem exists :-).

The funniest thing is - I served in army and shot a lot from fire arms - but this is something that human brain calculates and resolves without noticing too much :-)

avatar image Varmillion Oct 20 '17 at 01:44 AM

Yes, i made my whole game with a lot of mechanics, I left it at last thinking it was the simplest, and now here i am, breaking the head. I will try all the things that you guys said, thank you very much to try helping me!

avatar image ColdSteel48 Oct 20 '17 at 01:49 AM

You are welcome! :-)

avatar image staticvoidlol Oct 20 '17 at 01:56 AM

It's all for the digital karma! :P

avatar image ColdSteel48 Oct 20 '17 at 02:02 AM

Which is quite useless, you can't even make a bounty here (Or can I ? )

avatar image staticvoidlol Oct 20 '17 at 02:12 AM

As your self-appointed medical professional I am instructing you to get some rest right now :P. But yeah, I'm interested in hearing more about your Bounty System proposal (wouldn't that be GameDev consulting though?) in any case I have a strange compulsion in trying to reciprocate a small slice of what I think I've gained with the IP that Epic has made available for free. (I promise I don't work for said company (or even in game dev at all) lol).

avatar image ColdSteel48 Oct 20 '17 at 02:19 AM

Oh bounty is like in stackoverflow, if you have a question that noone answers for more than 2 days, you can offer a "bounty" amount of karma for someone who answers the question.

It would be a great improvement here - since it is very hard to get an answers especially in C++, it could maybe motivate ppl to answer more.

And then the comunity will get happier - because they will get more answers. A lot of ppl tried UE4 posted questions didnt get any answers and went back to Unity.

avatar image ColdSteel48 Oct 20 '17 at 02:21 AM

I think I will go to a night/morning run, and then will back of to sleep. for some reason my working hours are messed up in last couple of months

avatar image staticvoidlol Oct 20 '17 at 01:45 AM

Yeah - totally understood (similarly I've never really worked in 3rd person either lol), and at the risk of going off-topic here, in my personal little opinion I've found that attempting to answer questions here is a great way of forcing myself to try and solve a problem out of my comfort zone, which is in turn tricking myself into learning more :P.

avatar image ColdSteel48 Oct 20 '17 at 01:47 AM

Thats totally true - in general answering question is quite good way to learn by yourself :-).

avatar image Varmillion Oct 20 '17 at 01:52 AM

I come here after trying a lot, i have spended almost two days searching and trying different stuffs. I'm so so tired now, and will try tomorrow, anyway, thanks again. Cheers!

avatar image ColdSteel48 Oct 20 '17 at 01:53 AM

Sure, if you will get stuck too much I will post an example code snippet for you.

It is a great habit to try and solve things by your swlf before asking! I respect it :-)

avatar image Varmillion Oct 21 '17 at 05:29 AM

I'm trying to solve that. (i'm getting some random directions D:)

         UWorld* World = GetWorld();
     FVector2D Viewport;
     World->GetGameViewport()->GetViewportSize(Viewport);
 
     FVector WorldPosition;
     FVector WorldDirection;
     const FVector StartTrace = CurrentWeapon->WeaponMesh->GetSocketLocation("MF");
 
     AMyPlayerController* MyPC = Cast<AMyPlayerController>(Controller);
     if(    MyPC->DeprojectScreenPositionToWorld((Viewport.X), (Viewport.Y), WorldPosition, WorldDirection))
         GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Blue, TEXT("Deprojected!"));
 
 
 
     FActorSpawnParameters SpawnParams;
     SpawnParams.Owner = this;
 
     FVector Destination = (WorldPosition + WorldDirection) * CurrentWeapon->WeaponConfig.WeaponRange;
 
     FHitResult Hit = WeaponTrace(WorldPosition, Destination);
 
     FVector RotNorm = (Destination  - StartTrace);
 
     if(RotNorm.Normalize())
         GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Purple, TEXT("Normalized!"));
 
     FRotator Rot = RotNorm.Rotation();
 
     AWeaponBullet* Projectile = World->SpawnActor<AWeaponBullet>(ProjectileClass, StartTrace , Rot, SpawnParams);


i'm doing something wrong? (I have some debug things, like lines. I have removed from this anwser)

PHOTOS

PS:

Range = 3000.0f; "MF" = "Muzzle Flash"

PS2: AHUD Is not working (is not updating my Position and Direction), i did all right, getting and casting my HUD (and I checked if I succeeded on cast), so, Controller is working well.

(I also tried divide by 2 the X an Y viewport) and this Hit.Location()

avatar image ColdSteel48 Oct 21 '17 at 08:50 AM

Hi, sorry I am too tired right now, I just took a quick look and found something:

if( MyPC->DeprojectScreenPositionToWorld((Viewport.X), (Viewport.Y), WorldPosition, WorldDirection))

if you want to get the screen center you have to devide the size by 2 or even better to multiply it by 0.5 :)

if( MyPC->DeprojectScreenPositionToWorld((Viewport.X 0.5f), (Viewport.Y 0.5f), WorldPosition, WorldDirection))

P.S. for me the deproject works fine I am on 4.16.3 though...

If you can't get the screen size maybe you can try this function

const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY());

avatar image Varmillion Oct 21 '17 at 09:41 PM

Ok, i'm not in my home, i will see later. But thanks for giving a look! (I was dividing by two, but forgot to make the *0.5)

avatar image ColdSteel48 Oct 21 '17 at 09:56 PM

Multiplying by half nowadays is actually generates the same assembly code, since compilers improved a lot, and actually optimizing divisions by power of 2 I just think that this is still good habbit where you don't much care about precision and care about performance.

I will give you a code snippet to get you started in around 2 hours, since I dont know how did you inplement the weapon trace function - there could be an edge case which i will show you.

avatar image ColdSteel48 Oct 22 '17 at 01:27 AM

Hey mate, sorry I am short on time :(

But I want to point you some edge cases for your trace function: You must check if there was a blocking hit in your trace - if there was so just return the hit location, else you shall return start + destination and it will be the point you will shot at.

avatar image Varmillion Oct 24 '17 at 01:11 AM

I did it! I analyzed the "static" code and spawned the project from muzzle to BulletVelocity.Rotation (), the only thing I did not use was "BulletVelocity * = ProjectileSpeed", because I already have a ProjectileSpeed on MovementComponent with an GravityScale value. Thanks a lot you all, i have learned so much with this, and i'm trying to improve my math. Thanks for the patience. (A little of OFF, Dindi#6313 my discord if you guys want to talk sometime! (: ) Cheeeeeers!

avatar image ColdSteel48 Oct 24 '17 at 01:55 AM

Hey, great to hear that you solved this :-). I preffer chat apps like skype :-P you can find me there skype name "roma-mtfdb" I don't have an internet connection right now... probably will be back in couple of hours.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

This is a math problem. if you're using blueprint, I don't know if blueprint has said function

more ▼

answered Oct 21 '17 at 03:08 PM

avatar image

krisgoku2
96 5 8 11

avatar image Varmillion Oct 21 '17 at 09:37 PM

Yes, I'm trying to improve my math skills

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question