Problems with Camera in networking with Unreal engine 4 - c++

I am currently working on a project where all my players use different Camera.
I first thought using UCameraComponent, but each camera has to turn around a certain point and not moving with the movement of the pawns.
So I decided to Spawn a Camera Actor in the BeginPlay() of my pawn.
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
if (!hasCamera) { // Camera not set yet
FVector vectpos; // Target position of the camera
vectpos.X = -1130;
vectpos.Y = 10;
vectpos.Z = 565;
FRotator rotation;
rotation.Pitch = -22;
rotation.Yaw = 0;
rotation.Roll = 0;
APlayerController* controller = Cast<APlayerController>(GetController());
if (controller == NULL) // When I'm on client, the GetController() return NULL.
{
// Trying to find the controller of my client
for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
controller = *Iterator;
//On client, there is only 1 controller according to the documentation.
}
}
if (controller != NULL)
{
controller->SetViewTarget(Camera); // Set the view with the new camera
}
SetCamera(true); // Call and RPC Function to update the hasCamera variable
}
}
This is working for the first player, and after that it depends. Sometimes, the second player get a camera that works fine, but sometimes, he is viewing through the wrong camera and the Camera variable is not the same one he is looking in. Sometimes, when a new players join the game, it make the first/second player looking through the wrong camera.
Here is the GameInstance Blueprint we use to make the LAN Connection bewteen the clients and the server(the first client to create the game)
If someone can find why the camera is not working as expected , it would be very nice ! Thanks you all in advance for your help.

Apparently, You choose the wrong way.
In UE4 'ACharacter' (APawn to be precise) is a character representation in the world, so you will have one for every single player. Thus, it is strange to put your camera code in it.
You should make your own controller (ex. 'AMyPlayerController') and control camera from it. Obviously, only for a local player.

Related

UE4 - How do I get actors of an array to follow the previous actor like in Snake?

I am new to C++ and even newer to UE4.
I am trying to create a Snake game but I am having trouble getting the body segments of the snake to move like they should in Snake. Like a train of actors. How do I get the body to move like a train/snake in the Snake game?
I've made a gif to try and show the problem (sorry if it is too small).Snake segment movement problem
The green actor is the Snake's head and the yellow actors are the segments that spawn (currently when I press space bar).
I can post code snipets if that helps?
The github repo is here: https://github.com/joeyisplaying/SnakeGame/tree/dev-branch/Source/SnakeGame
SOLVED! For anyone having this problem, I managed to find a really simple solution in a video on YouTube for this. My code now looks like this:
void ASnake::UpdateTailSegmentLoc()
{
if(!TailSegment)
{
return;
}
if(TailSegment)
{
for (int32 i = 0; i < TailSegmentArray.Num(); i++)
{
const FVector CurrentSectionLoc = TailSegmentArray[i]->GetActorLocation();
TailSegmentArray[i]->SetActorLocation(PreviousTailSegmentLoc);
PreviousTailSegmentLoc = CurrentSectionLoc;
}
}
}
The tick looks like this now:
// Called every frame
void ASnake::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
PreviousTailSegmentLoc = SnakeHead->GetComponentLocation();
if(!MovementDirection.IsZero())
{
const FVector NewLocation = SnakeHead->GetRelativeLocation() + (MovementDirection * DeltaTime * SnakeHeadSpeed);
SnakeHead->SetRelativeLocation(NewLocation);
UpdateTailSegmentLoc();
}
}
The YouTube video is here: https://www.youtube.com/watch?v=x8s86k6JUl8

How do I accomplish proper trajectory with a Cocos2d-x node using Chipmunk 2D impulses and rotation?

I'm building a game with Cocos2d-x version 3.13.1 and I've decided to go with the built-in physics engine (Chipmunk 2D) to accomplish animations and collision detection. I have a simple projectile called BulletUnit that inherits from cocos2d::Node. It has a child sprite that displays artwork, and a rectangular physics body with the same dimensions as the artwork.
The BulletUnit has a method called fireAtPoint, which determines the angle between itself and the point specified, then sets the initial velocity based on the angle. On each update cycle, acceleration is applied to the projectile. This is done by applying impulses to the body based on an acceleration variable and the angle calculated in fireAtPoint. Here's the code:
bool BulletUnit::init() {
if (!Unit::init()) return false;
displaySprite_ = Sprite::createWithSpriteFrameName(frameName_);
this->addChild(displaySprite_);
auto physicsBody = PhysicsBody::createBox(displaySprite_->getContentSize());
physicsBody->setCollisionBitmask(0);
this->setPhysicsBody(physicsBody);
return true;
}
void BulletUnit::update(float dt) {
auto mass = this->getPhysicsBody()->getMass();
this->getPhysicsBody()->applyImpulse({
acceleration_ * mass * cosf(angle_),
acceleration_ * mass * sinf(angle_)
});
}
void BulletUnit::fireAtPoint(const Point &point) {
angle_ = Trig::angleBetweenPoints(this->getPosition(), point);
auto physicsBody = this->getPhysicsBody();
physicsBody->setVelocityLimit(maxSpeed_);
physicsBody->setVelocity({
startingSpeed_ * cosf(angle_),
startingSpeed_ * sinf(angle_)
});
}
This works exactly as I want it to. You can see in the image below, my bullets are accelerating as planned and traveling directly towards my mouse clicks.
But, there's one obvious flaw: the bullet is remaining flat instead of rotating to "point" towards the target. So, I adjust fireAtPoint to apply a rotation to the node. Here's the updated method:
void BulletUnit::fireAtPoint(const Point &point) {
angle_ = Trig::angleBetweenPoints(this->getPosition(), point);
// This rotates the node to make it point towards the target
this->setRotation(angle_ * -180.0f/M_PI);
auto physicsBody = this->getPhysicsBody();
physicsBody->setVelocityLimit(maxSpeed_);
physicsBody->setVelocity({
startingSpeed_ * cosf(angle_),
startingSpeed_ * sinf(angle_)
});
}
This almost works. The bullet is pointing in the right direction, but the trajectory is now way off and seems to be arcing away from the target as a result of the rotation: the more drastic the rotation, the more drastic the arcing. The following image illustrates what's happening:
So, it seems that setting the rotation is causing the physics engine to behave in a way I hadn't originally expected. I've been racking my brain on ways to correct the flight path, but so far, no luck! Any suggestions would be greatly apprecitated. Thanks!

AWheeledVehicle movement in c++

using Unreal Engine 4, I am attempting to move my vehicle (AWheeledVehicle) in the forward direction. I am correctly referencing the correct vehicle, but still it won't move.
Not sure what I'm doing wrong.
Attached below is my Vehicle and Controller class
AAIWheeledVehicle
AAIWheeledVehicle::AAIWheeledVehicle(){
AIControllerClass = AMyAIVehicleController::StaticClass();
}
AMyAIVehicleController
void AMyAIVehicleController::Possess(APawn *pawn){
Super::Possess(pawn);
//FVector location2 = pawn->GetActorLocation(); // -11310, 8910, 0
// initialize location of target point
location.X = -9620.0f;
location.Y = 8910.0f;
location.Z = 0.0f;
scaleValue = 1.0f;
target = GetWorld()->SpawnActor<ATargetPoint>(location, FRotator::ZeroRotator);
target->SetActorLocation(location);
// get AI vehicle reference
vehicle = Cast<AWheeledVehicle>(pawn);
// add forward movement to vehicle, scale = 1
vehicle->AddMovementInput(GetActorForwardVector(), scaleValue);
//vehicle->GetVehicleMovement()->Velocity.X = 1.0f;
//vehicle->GetVehicleMovement()->SetThrottleInput(1.0f);
//vehicle->GetVehicleMovement()->SetSteeringInput(1.0f);
//vehicle->GetVehicleMovement()->SetHandbrakeInput(false);
// set rotaion of vehicle to rotation of the target point
vehicle->SetActorRotation(target->GetActorRotation());
}
Vehicle setup in UE4 is tricky. It has a few moving parts that work together. Make sure that you have the initial vehicle setup working otherwise it may not move at all regardless of the code involved. (btw the code looks fine, but I recommend testing in blueprints to verify all is correct with setup)
I made a video about vehicle setup in UE4 on my channel, This might solve your problem. Go through and make sure the setup is the same, since you need to do this whether you are using C++ or blueprints. Here's the link:
UE4 - How to Make Vehicles

How to create Orbit Camera with zooming function

i am new to ogre and have read the basic tutorials but unable to understand how to create a orbit camera with mouse wheel zooming.
here is my camera code
// Create the scene node(orbit camera)
node = mSceneMgr->getRootSceneNode()->createChildSceneNode("orbit", Ogre::Vector3(0, 100, -150));
node->attachObject(mCamera);
// create the second camera node(freecam)
node = mSceneMgr->getRootSceneNode()->createChildSceneNode("free", Ogre::Vector3(0, 100, 400));
// create the third camera node (3rd person robot cam)
node = mSceneMgr->getRootSceneNode()->createChildSceneNode("robocam", Ogre::Vector3(0, 100, -80));
And here is my keypress function
bool BasicTutorial05::processUnbufferedInput(const Ogre::FrameEvent& evt)
{
Ogre::Vector3 transVector1 = Ogre::Vector3::ZERO;
if (cam1 == true)//when cam 1 is selected, bool cam1 will be true;
{
if (mKeyboard->isKeyDown(OIS::KC_S))
{
mSceneMgr->getSceneNode("orbit")->pitch(Ogre::Radian(-0.012f));
}
if (mKeyboard->isKeyDown(OIS::KC_W))
{
mSceneMgr->getSceneNode("orbit")->pitch(Ogre::Radian(0.012f));
}
if (mKeyboard->isKeyDown(OIS::KC_A))
{
mSceneMgr->getSceneNode("orbit")->yaw(Ogre::Radian(0.012f));
}
if (mKeyboard->isKeyDown(OIS::KC_D))
{
mSceneMgr->getSceneNode("orbit")->yaw(Ogre::Radian(-0.012f));
}
}
mSceneMgr->getSceneNode("orbit")->translate(transVector1 *evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
}
and the mouse wheel zooming
//zooming for orbit camera
Ogre::Vector3 transVector2 = Ogre::Vector3::ZERO;
if (mMouse->getMouseState().Z.rel != 0){
transVector2.z = -mMouse->getMouseState().Z.rel;
}
but i can able to sort of orbit around the point where the camera is but only when i use the wheel scroll zoom, instead of rotating around a point it rotates where the camera is.
How do i change it that it only rotates at a point?
Create two nodes for your camera - the first one is the target and it's placed at the point you want to rotate around.
The second node should be created at some distance from the first one. You should attach it as the child of the target and attach your camera to this node. Finally, you should point your camera at the target node (the first one).
With this setup you'll just need to put your target node at the point of your interest and rotate it as you want. The camera position will follow the target, because it's his child. And by moving your camera node closer to the target node you can change your zoom level.

Box2D creating rectangular bounding boxes around angled line bodies

I'm having a lot of trouble detecting collisions in a zero-G space game. Hopefully this image will help me explain:
http://i.stack.imgur.com/f7AHO.png
The white rectangle is a static body with a b2PolygonShape fixture attached, as such:
// Create the line physics body definition
b2BodyDef wallBodyDef;
wallBodyDef.position.Set(0.0f, 0.0f);
// Create the line physics body in the physics world
wallBodyDef.type = b2_staticBody; // Set as a static body
m_Body = world->CreateBody(&wallBodyDef);
// Create the vertex array which will be used to make the physics shape
b2Vec2 vertices[4];
vertices[0].Set(m_Point1.x, m_Point1.y); // Point 1
vertices[1].Set(m_Point1.x + (sin(angle - 90*(float)DEG_TO_RAD)*m_Thickness), m_Point1.y - (cos(angle - 90*(float)DEG_TO_RAD)*m_Thickness)); // Point 2
vertices[2].Set(m_Point2.x + (sin(angle - 90*(float)DEG_TO_RAD)*m_Thickness), m_Point2.y - (cos(angle - 90*(float)DEG_TO_RAD)*m_Thickness)); // Point 3
vertices[3].Set(m_Point2.x, m_Point2.y); // Point 3
int32 count = 4; // Vertex count
b2PolygonShape wallShape; // Create the line physics shape
wallShape.Set(vertices, count); // Set the physics shape using the vertex array above
// Define the dynamic body fixture
b2FixtureDef fixtureDef;
fixtureDef.shape = &wallShape; // Set the line shape
fixtureDef.density = 0.0f; // Set the density
fixtureDef.friction = 0.0f; // Set the friction
fixtureDef.restitution = 0.5f; // Set the restitution
// Add the shape to the body
m_Fixture = m_Body->CreateFixture(&fixtureDef);
m_Fixture->SetUserData("Wall");[/code]
You'll have to trust me that that makes the shape in the image. The physics simulation works perfectly, the player (small triangle) collides with the body with pixel perfect precision. However, I come to a problem when I try to determine when a collision takes place so I can remove health and what-not. The code I am using for this is as follows:
/*------ Check for collisions ------*/
if (m_Physics->GetWorld()->GetContactCount() > 0)
{
if (m_Physics->GetWorld()->GetContactList()->GetFixtureA()->GetUserData() == "Player" &&
m_Physics->GetWorld()->GetContactList()->GetFixtureB()->GetUserData() == "Wall")
{
m_Player->CollideWall();
}
}
I'm aware there are probably better ways to do collisions, but I'm just a beginner and haven't found anywhere that explains how to do listeners and callbacks well enough for me to understand. The problem I have is that GetContactCount() shows a contact whenever the player body enters the purple box above. Obviously there is a rectangular bounding box being created that encompasses the white rectangle.
I've tried making the fixture an EdgeShape, and the same thing happens. Does anyone have any idea what is going on here? I'd really like to get collision nailed so I can move on to other things. Thank you very much for any help.
The bounding box is an AABB (axis aligned bounding box) which means it will always be aligned with the the Cartesian axes. AABBs are normally used for broadphase collision detection because it's a relatively simple (and inexpensive) computation.
You need to make sure that you're testing against the OBB (oriented bounding box) for the objects if you want more accurate (but not pixel perfect, as Micah pointed out) results.
Also, I agree with Micah's answer that you will most likely need a more general system for handling collisions. Even if you only ever have just walls and the player, there's no guarantee that which object will be A and which will be B. And as you add other object types, this will quickly unravel.
Creating the contact listener isn't terribly difficult, from the docs (added to attempt to handle your situation):
class MyContactListener:public b2ContactListener
{
private:
PlayerClass *m_Player;
public:
MyContactListener(PlayerClass *player) : m_Player(player)
{ }
void BeginContact(b2Contact* contact)
{ /* handle begin event */ }
void EndContact(b2Contact* contact)
{
if (contact->GetFixtureA()->GetUserData() == m_Player
|| contact->GetFixtureB()->GetUserData() == m_Player)
{
m_Player->CollideWall();
}
}
/* we're not interested in these for the time being */
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{ /* handle pre-solve event */ }
void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
{ /* handle post-solve event */ }
};
This requires you to assign m_Player to the player's fixture's user data field. Then you can use the contact listener like so:
m_Physics->GetWorld()->SetContactListener(new MyContactListener(m_Player));
How do you know GetFixtureA is the player and B is the wall? Could it be reversed? Could there be an FixtureC? I would think you would need a more generic solution.
I've used a similar graphics framework (Qt) and it had something so you could grab any two objects and call something like 'hasCollided' which would return a bool. You could get away with not using a callback and just call it in the drawScene() or check it periodically.
In Box2D the existence of a contact just means that the AABBs of two fixtures overlaps. It does not necessarily mean that the shapes of the fixtures themselves are touching.
You can use the IsTouching() function of a contact to check if the shapes are actually touching, but the preferred way to deal with collisions is to use the callback feature to have the engine tell you whenever two fixtures start/stop touching. Using callbacks is much more efficient and easier to manage in the long run, though it may be a little more effort to set up initially and there are a few things to be careful about - see here for an example: http://www.iforce2d.net/b2dtut/collision-callbacks