So here’s a simple example implementation.
Now I’ve highlighted the important bits in colored boxes. (everything is highlighted!!!)
Green Box - Here we pass in an inspect object. This could be triggered from anywhere, it doesn’t matter. We’re checking for if we already have an inspect object, because if we do then that reference would be valid. Since it isn’t (hypothetically) we can safely say we don’t have one. We go ahead and set that reference to our new inspect object - now it’s valid. We also store the actor transform.
Yellow/Orange Box - Some will say this shouldn’t be on tick, but this will update the location of our inspect object every frame, along with it’s rotation. We wouldn’t need this if we were going to lock the player in, but I’m imagining the most basic implementation here. The red box specifically will be explained lower, but this is a location in front of our camera. Over to the right, we’re adding a rotation to the actor’s world rotation. This will allow you to spin the object around. A more robust implementation might also rotate the object around so that if you just spun the player character around then the object would continue facing the player. To do that, you’d want to store and modify a rotation offset and apply that after you’d calculated the rotation you need to face the player. The blue box will be explained as well.
Red Box - So we get the camera’s location as a base, but we can’t use that or the object would literally be inside the camera. Not good. So we get the forward vector, which is a normalized vector (scale/length of 1) that gives us the direction the camera is pointed. The specifics of why this works would be better taught by someone else, but just know that you need a direction relative to the camera. Anyway, we multiply (scale) the vector by a float value for the distance we want the object to ‘float’ in front of us. This is the relative offset we want the object to have to us.
Blue Box - Here we’re getting the current mouse X axis, multiplying it by a mouse speed multiplier and multiplying that by Delta Seconds (time since last frame). This is a good practice because it keeps the logic frame-independent. It will always take into account any differences in frame-time and always behave in an expected way. The reason we’re doing this here and not for the location is that setting the location is not a rate-of-change process, but this is. If we were interpolating the position, then we would need delta seconds for location, but there is a node for that. Anyway, the float value ‘Mouse Rotation Speed’ will allow you to set how much the mouse can rotate the object per second, no matter the frame-rate.
Purple Box - Alright, so this is where we drop everything. We want to make sure we actually do have an inspect object here, and if we do we’re going to use a handoff. We set a temporary reference to our inspect object and set the inspect object to nothing. That variable is no longer valid- remember the other gates checking validity? We do this so none of the other logic will change this actor. Then, we set temp’s transform back to it’s original. That’s assuming you want to put it exactly back where it goes, otherwise you could just drop it and let it start simulating physics (or indeed apply an impulse). Lastly we set temp to nothing as we no longer need to keep up with it. Technically we don’t need to do this because we set temp before use every time.
Of course, this is very very basic, and won’t hold a candle to Gone Home- but it’s a start. This doesn’t filter for any specific class or tag (or indeed weight), and in fact never gets called because I didn’t set that up. Additionally, you could even start dropping some depth of field and focus Post effects in and really tune it up (if you wanted), and you could add a pan forward/back feature as well. There is also a physics handle component that you can use in Unreal, but I didn’t use that here. Lots you can do but this is a simple implementation to get your feet wet.
I just wanted to give you a basic idea on how to do it.