I am working on a character controller for a 3D platformer in Unity. I cannot find an approach that satisfies me.
I have experimented with these approaches in order to learn about their virtues and pitfalls:
Rigidbody + CapsuleCollider + native physics system (gives you something like Fall Guys)
Rigidbody + CapsuleCollider + custom velocity handling, only using physics system to resolve collisions (this method is illustrated in Catlike Coding tutorial here)
Built-in CharacterController
Custom character controller that uses Unity methods to detect geometric collisions, but does its own collision resolution via depenetration (this method is illustrated in Roystan Ross tutorial here)
See also this video by iHeartGameDev summarizing different approaches.
For my particular use case, each one of these has been better than the last.
After following Roystan's tutorial, I am a big fan of the pushback method of handling collision. Rather than use casts to catch collision before you move your object, you move your object, then find collisions, then resolve them using depenetration.
Roystan's method represents the character as a stack of three spheres for the same reason people favor capsule colliders in 3D: it makes handling slopes much easier (and also because depenetration is easier when you think in terms of spheres).
But the thing I am struggling with is that I don't want the player to be able to slide up or down ledges when traversing them.
Basically, when jumping up or walking off a ledge, I want my character to be treated as a box.
So I am struggling to find a way to accommodate both of the following:
I want to support sloped MeshCollider ground (not too noisy, but will definitely be possible to have 4 collision points at a time)
I want ledge traversal (up and down) to treat my player as a box
Here are diagrams illustrating what you normally get with a capsule, versus what I want.
Down ledge:
Up ledge:
My thinking is that I have two options:
Represent the character as a box and use box depenetration techniques to move him along sloped ground (for example, using Unity's ComputePenetration())
Represent the character as a capsule (or stack of three spheres like in Roystan's tutorial) and add special case logic to get the boxy ledge traversal I want
One problem I can foresee with approach 1 is properly doing the depenentration on noisy sloped ground, and one problem I can foresee with approach 2 is properly writing the special cases. (My game is relatively low-poly and retro-styled, so I wouldn't mind the player not appearing perfectly flush with slopes that comes with the box representation of approach 1.)
In any event, I am just looking for advice on how to proceed with this problem. How can I get the boxy handling of ledges while also getting traversal on sloped MeshCollider terrain.
Is either of these approaches better than the other for what I am after, and is there an alternative approach I haven't considered?
Inside Out 2, the highly-anticipated sequel to the 2015 original, made us feel all the feelings when it debuted in June of this year. After earning more than $1 billion at the box office, it’s officially the biggest movie of the year. Inside Out 2 faces the horrors of puberty with a host of new emotions such as Envy,…
Everybody has several games that mean quite a lot to them. For me, one of these games is Indiana Jones and the Infernal Machine. I not only grew up with this game, but I also have a lot of memories of this game. Outside of that, I also met some amazing friends through the community behind this game. I even did several speedruns of this game, and I’m an active member of the community. Now, color me surprised that 25 years after the release of this game, we got new fan-made content for this game. Not just fan made content in the style of fan patches to solve bugs with the game, a whole new level and promises of a level editor to create even more new custom content. This blew me off my socks and in today’s article I want to talk about it. So strap in andlet’s get ready to play new content for one of the best Indiana Jones games ever made.
The new level – SED
There is a speedrunning discord server for this game. Well, it was a speedrunning discord server but for a few years now, this server has grown into a server of people who appreciate this game. If you want to join this discord, here is an invite link. When the server started to grow, several modders joined our server. One of these modders is going under the name of Urgon (currently) and what we didn’t know is that he was decompiling the whole game. Not only that, he was creating a level editor based upon an existing level editor.
This existing level editor is for Star Wars Jedi Knight & Mysteries of the Sith. Those games used an engine that formed the basis for the Jones3D engine. While he was developing that editor, he tested his skills by creating a new level. So, basically, parts of this new level are tests of the new level editor and what you can do with it.
Now, information about this new level and the download link can be found at this GitHub repository. If you want to download the actual level, you have to go to this page and click the green button named “Code”. In that dropdown, you can choose “download zip”. You’ll need that later if you want to install/play this custom level. Now, if you read the pre-mod or the installation instructions for this level, you might feel overwhelmed if you aren’t very technically inclined. That’s why two community members wrote two special tools to aid you in preparing your game.
You might ask yourself, like Klamath did in at the end of our stream of this custom level, why are there two tools for basically the same? Well, let me tell you the history about it. When I wanted to play the custom level, I had a bit of trouble myself while figuring out the tutorial. I also found that the required steps were quite a lot to do. So, I decided to start writing a PowerShell script that did all the steps. I announced that in the Indy3D discord that I was writing this. When I almost completed my tool, the_Kovic dropped his version of the tool.
Personally, I didn’t want to throw my work out the window and continued finishing my GUI version. When I finished, I didn’t convert my tool to an EXE and left it just as a script file you could run using a command line or a code editor. The next day, Kovic released a GUI version of his tool and I gave some feedback on his tool. In the days after that, I created an EXE version of my tool and we both kept adding features in our tool. He wrote his tool in C#, which is a bit friendlier to create an EXE. If I didn’t release my first version as a script only and converted it to an EXE, I think it might have been less overwhelming for people.
That said, Kovic thanked me for creating my tool since like he said on our stream: “It put my butt into gear to create a tool and write a GUI, which I normally don’t write“. On top of that, our tools aren’t meant to compete with each other. I can’t write C# and Kovic can’t write PowerShell. And it would be a shame to just delete work because somebody else was quicker or made their tool more user-friendly first. The result now is that we both have two very strong tools with a very similar, maybe even completely the same, feature set.
Outside a different choice of coding language, the biggest differences between both our tools are under the hood. In Kovic’s tool, you get more files than in my tool when you download the tool. And that’s because to prepare your game for custom levels, you need to extract several files in the resource folder. The tool used for extraction has a bug where instead of extracting the folders of the archive into the resource folder, it extracts them into separate folders, like if you would extract a zip file. Kovic packs a modified version of this extraction tool so that part of the process goes a bit faster. In my version, the tool just downloads the latest official versions of the tool and prepare the game that way.
In the end, both our tools give you the same end result. They prepare your game to install custom levels and play them. If you want to try out the_kovic’s tool, you can find the latest version on this releases page. If you want to try our my tool, you can find it on this releases page. Feedback to our tools is always welcome! If you find an issue or if you have an idea, feel free to hit us up, and we will look into it.
Earlier I talked about a stream of the level we did. Klamath, the_Kovic and me did a live stream where we played through this level. Now, I have to emphasize that release of this level is an impressive technical achievement. Creating a level for a 3D game isn’t easy and requires a lot of work. It’s even more impressive when you know that not everything is documented about the engine, and you have to decompile a lot of it. In the next part of this article, I’m going to talk about the level itself and critique it.
If you don’t want spoilers, I’d advise you to skip that section for now and come back later. Now, I want to say that I start reviewing the level in a moment, but this feedback is mostly meant for people who want to make new custom content. What did this new level do right and wrong if you look at it as a player who doesn’t know the technical background of this level? This isn’t meant to break down the amazing work the modders did to make this work.
Reviewing the new level
Editorial note: this review will spoil quite a lot. If you don’t want to get spoiled, you have to skip this section of the article. This isn’t a walkthrough of the level either. Some sections are skipped, I’m only going to talk about the sections I want to talk about.
The new level takes place 25 years after the ending of the original game. Indy returns to his Canyonlands dig site. You are set loose at the tent where Sophia picked Indy up with a helicopter to start the Infernal Machine adventure.
In terms of new content, there isn’t a lot new to see. Some ladders are missing and some parts of the level are blocked off. Also, all treasures are missing that you would usually find in the level.
Before I continue, I want to mention that some parts of this level are made quite difficult on purpose. The developer wanted to give us the feeling we were young kids again, playing this game for the first time, and have us figure out the new puzzles by ourselves. Yet, finding a correct balance between difficulty and unfair is a very fine line to thread. Personally, I think that in some sections, the developer crossed the line into unfair level design.
When running on the top section, you notice that there are some new voice lines. These voice lines are made possible with a voice cloning AI tool that was trained on lines from Doug Lee, the original voice actor for this game. The new voice lines sound amazing, and if you didn’t know better, you’d think that Doug Lee came back to record the new lines. In most cases, these voice lines really fit Indy’s personality and fit right into the game.
We come to our first snag when we want to go to the new content. I can understand not seeing the shovel and being confused, since it’s hanging at the jeep on top. And you know what’s even more confusing, the other side of the jeep model has a shovel in its texture! Anyhow, when you pick up the shovel and dig up the Infernal Machine part, it’s clear that you need to break a wall. Here comes one of the worst parts of this level. The location of this cracked wall is insanely well hidden. It’s in one of the last places you’d look, and several of the first players ran around for hours upon hours in Canyonlands before it was found. And when it was found, it made us annoyed.
It’s a clear example of how players who are used to the level, overlooking the obvious. The wall you need to break has an actual cracked wall texture, but it’s behind something you can’t see through. I think it would have been fine if the location, where it is at, had a bigger ledge so you’d notice it somewhat instead of just having to go on a wild goose chase.
Now, we enter the new area. We come to a big open space where the next set of puzzles are. The first puzzle is actually a jumping puzzle. Now, I highly advise you to not play this level if you haven’t played through most of Indiana Jones and the Infernal Machine. Not that there are spoilers, but because some of the jumps in this level are straight up difficult and not what you really expect from this game. Kovic calls it “Kaizo Jones” for a good reason.
There are some small platforms and not having the look key working is going to be a pain in this section. Since, there are some moments where you need to be able to free look and not being able to see beneath or above you will make things a lot more tricky. After you finished these jumps, you might start to notice that the developer of this custom level added some details. Like, the rope bridges are gently moving in the wind. This is something that isn’t present in the original game. It’s a new “COG” script that makes that possible.
These cog scripts are a blessing for custom content. Since, this game isn’t hardcoded at all, so if you learn how to write these cog scripts, you can basically write new mechanics as well. It’s insane what possibilities there are going to be in the future for this game. I hope there is going to be good documentation so that custom level creaters know what’s possible and what’s impossible with the level editor.
While you are exploring this area, you notice that it’s huge. This also explains why it takes quite a while to load this level. Currently, modders are looking into why it’s running so slow. Since, we don’t really know if it’s the level size or something else slowing down the loading of this level.
So, after jumping around the central column, you’ll arive at the shed. Here you notice you can actually enter the shed from the top. Kovic explains it quite well during the stream. If you want to hear some technical explanations on how this level works, I’d advice you to watch our stream. Since there is a lot of interesting development talk in there. Later, Kovic and myself had a contest in trying to quote voice lines from the main game. We got close to 200. Kovic won that because I said a line he already said.
After you picked up everything from this shed and climbed outside, you experience another new mechanic of this game. It’s a mechanic that gets backported from Indiana Jones and the Emperor’s Tomb. The fact you can use your whip to go over a zipline.
After you returned and struggled with getting across the other bridge, you will encounter other parts of this level. Here you’ll encounter two voice lines that straight up lie to you. The first voice line is that you need more force, explosives to break a rock that’s blocking your way forwards. Here is the issue with that, you get an explosive barrel later. You need to find an extremely hidden swim tunnel in the water. It’s not the only hidden thing in the water, so investigate behind and underneath rocks quite well. Since, these puzzles in this water border in the unfair territory. What makes that explosive voice line even more evil is that there is a box of TNT in the shed earlier. But what’s the second voice line that lies to you?
Well, that is after you made your way past said boulder. You find a minecart and interacting with it, Indy says that it will run with gasoline. And there is still gasoline left in the shed. Sadly, you can’t pick it up anymore. Now, this is a red haring, you don’t need this minecart at all.
By now, you have learned that this level likes to break the rules of how the main game is designed. You’ll have to think outside of the box sometimes to beat this level. But, for some jumps, you need to use your knowledge of what’s possible and impossible to progress. This makes it quite tricky sometimes to progress. And this brings me to a conclusion we also said on stream. I think that the issue is that people expected a more tame level than what we actually got and that might turn some people off. But, I’m so glad that the quick save system exists in this game. So, abuse the quick save system and make multiple saves since you’ll need them if you aren’t a veteran player of this game.
Anyhow, let’s get back into the flow of the level. After we completed the lever puzzle, we go back towards to the huge open area and take the lift to a new location. What follows is a totally new area where it’s a good thing if you saved up on health packs and you have a great sense of direction.
So, the short minecart ridge comes to an end. It doesn’t take long before you find yourself into a watermaze. This watermaze is unfair in my honest opinion. Klamath had a tricky time solving it and he had to use almost every health pack to get through it. Without Kovic pointing out the right tunnel, I think it would have made the stream quite a bit longer. There was supposed to be a minecart section instead of this swimming maze, but the developer had a hard time making the minecart section to work and he gave up and made this swimming maze.
Now, I’m all fine with this swimming maze, but the map glitches out at certain parts. I have a mediocre sense of direction and I wanted to rely on the map. The map doesn’t always render the tunnels correctly. You sometimes swim off the map or “in nothingness”. Sadly, I have to draw my own map. I wish I still had it, since it would make for a nice screenshot here… But I threw it out but me and my clumsiness… I knocked over my waterbottle over it.
After the swimming maze, we get a new section of “Kaizo Jones”. Where we get some extremely tricky platforming. Here is where you need to use the look key again and be sure you are playing in 4:3. If you are playing in another resolution like 16:9 or 16:10, this will also be one of the moments where you don’t see all the information.
The block puzzle that follows, feels right out of Tomb Raider. The initial reviews of this game called out this game as a Tomb Raider clone. While, this game does the formula a whole lot differently. We even talked about that during the stream. In terms of theming, Infernal Machine is a lot better. Tomb Raider feels like obstacle courses. But that’s thanks to a different engine and control style. If you want to hear the whole discussion, you can watch the stream from this point. Excuse Kovic’s internet being spotty while he was replying.
After the block puzzle, a new path opens in the swim maze. Then, some platforming comes. Something I love is how there is even a troll hidden inside the platforming. It caught me off guard and made me smile. This platforming section was also love to do. It felt like a real test on how well I know the game. This platforming section feels a lot better put together and feel less cryptic on where you need to go next. You really start to notice that the developer was getting more used to the level editor and made better puzzles. The moment of having to use the whip to swing over the gap while the platform underneath you was breaking was amazing.
After that, we get into the finale of this level. We jump into a portal and we land in a playable area which is shown at the end of Shambala, the 4th level in the original game. That area that’s shown to you after you have beaten the Ice Guardian. The path that takes you to Palawan Lagoon. It was possible to explore that using cheats and modified saves, but now it’s in a level for real. Exploring the little house at the end brings us to something you totally don’t expect this custom level to do. You’ll find a parchment inside with a riddle and at the end you notice something in red saying: “MAT -> ZIP”.
There is some meta gaming now going on. You’ll need to make a hard save and exit your game. You’ll need to go to your resource folder & then open the MAT folder. In there you’ll need to rename “SED.MAT” to “SED.ZIP”. You’ll also need to enter the password for the zip, since you get a new cog script to continue the level, which you need to place in your cog folder. In there, there is another surprise. But, that’s something I’m not going to spoil. But, be sure that Kovic is playing with that surprise and maybe I’m going to dig into it. PS, the next paragraph is in white with the right spelling of the password:
Marcus
The way the level ends is bittersweet. If you solve the final puzzle, something special happens and you can beat the level. You could argue that the ending of this level is “lazy” or “creative”… But, it’s an amazing way to wrap up the story in one level with a nice bow.
At the start of the custom level, I felt that it was quite rough around the edges and it had some moments that felt badly designed. In terms of game design that is. If you look at it visually and level flow wise, I personally think that this level would fit right into the original game as a final challenge. But, the further you go into the level, the more you start to notice that the developer of this level is getting used to the tools and the editor and more polished puzzles and area’s are coming through. You notice the journey of the developer and see it becoming better and better.
I want to give a big congrats to everybody who was involved in releasing this custom level. It’s a blast to play and I can’t wait to see more custom levels. The stream I did with this level was one of the best streams ever and it was also quite a lot of fun to write the tool to help people play this custom level. I’m curious what you think about this custom level and/or the content of this article. Feel free to drop something in the comment section down below.
And with that, I have said everything I wanted to say about this for now. I want to thank you so much for reading and I hope you enjoyed it as much as I enjoyed writing it. I hope to welcome you back in another article but until then, have a great rest of your day and take care.
I'm trying to create a particle simulation (solar system kind). Until now my particles have no spin so the collision is rather simple
void collide(const Particle& b) {
const Vector3d normal = math::normal(position(), b.position());
const Vector3d relativeVelocity = velocity() - b.velocity();
const double dot = math::dot(relativeVelocity, normal);
const Vector3d work = normal * dot;
_velocity = _velocity - work;
}
Since I've read that particle spin plays a huge part in such simulations I'm trying to implement angular momentum but unfortunately this exceeds my math skills. I tried searching the internet for quite a while now for any source I understand but I'm at the brink of giving up.
How can I integrate particle spin into my code? I can work with any kind of (pseudo) code as long as the variables are somewhat clear. Particles are rigid spheres with mass = volume.
Edit:
Dont get hang up on what the simulation is trying to achieve. The task can be simplified down to: Two rigid spheres collide in space. Calculate their motion and spin after the collision.
I've written two main functions who's purpose is to detect and resolve collisions between a moving rectangle and a non-moving rectangle. I have a decent understanding of how the algorithm works, and in practice it works very nicely... except for of course the classic tiny bug that drives everyone insane!
Overall, the functionality goes like this. You have a rectangle with a velocity, and one that doesn't. Using the velocity of one rectangle, you determine if and when (along the velocity vector) a collision occurs with the other rectangle. Then using the time of the collision, you adjust the velocity component to avoid collision.
This works pretty great, in 99% of cases! Moving the player rectangle towards the target rectangle yields the right results at most angles, however like 8 specific (and relatively common) cases mess the whole thing up.
For example, when I move the player rectangle until it's collided with the top side of the target rectangle, that lines it up so the bottom of the player is touching the top of the target. Then if I move the player directly to either side, and try to move back, the player gets snagged on the corner of the target and cannot proceed. At this point, only the corners of each rectangle are barely touching.
Of course, for an added layer of "what's going on?" this only applies to the top, bottom and right sides of the target rectangle. When I've tried the same thing on the left side of the target, the player still experiences effects but it's not a full stop; it's merely just a slowing down.
In order to figure out what it could be, it's necessary to look directly at how the code works. The function rayVsRect is responsible for checking the velocity against a rectangle, and finding the time of the collision (alongside returning other useful stuff like a contact point and a normal vector). rectVsRect is responsible for carrying out collision detection between the two rectangles. It expands the target rectangle by the dimensions of the other rectangle. That way we can simply use the rayVsRect function to get the same values we want. The language is lua by the way, just in case that makes a difference to know, maybe perhaps in knowing the subtleties of how data is stored or other fun stuff like that. Who knows? (Hopefully it's not that)
function rayVsRect(ray, rectangle)
local invDir = {vx = 1 / ray.vx, vy = 1 / ray.vy}
local nearX = (rectangle.x - ray.x) * invDir.vx
local nearY = (rectangle.y - ray.y) * invDir.vy
local farX = (rectangle.x + rectangle.width - ray.x) * invDir.vx
local farY = (rectangle.y + rectangle.height - ray.y) * invDir.vy
--Turn nan values into "infinity"
if nearX ~= nearX then
nearX = 4294967296 * math.sign(rectangle.x - ray.x)
farX = 4294967296 * math.sign(rectangle.x + rectangle.width - ray.x)
end
if nearY ~= nearY then
nearY = 4294967296 * math.sign(rectangle.y - ray.y)
farY = 4294967296 * math.sign(rectangle.y + rectangle.height - ray.y)
end
if farX < nearX then farX, nearX = nearX, farX end
if farY < nearY then farY, nearY = nearY, farY end
if (nearX > farY) or (nearY > farX) then return 0 end
local contactTime = math.max(nearX, nearY)
local farContactTime = math.min(farX, farY)
if farContactTime < 0 then return 0 end
local contactPoint = {x = ray.x + contactTime * ray.vx, y = ray.y + contactTime * ray.vy}
local contactNormal = {x = 0, y = 0}
if nearX < nearY then
if ray.vy > 0 then
contactNormal.y = -1
else
contactNormal.y = 1
end
else
if ray.vx > 0 then
contactNormal.x = -1
else
contactNormal.x = 1
end
end
return {contactTime = contactTime, contactPoint = contactPoint, contactNormal = contactNormal}
end
function rectVsRect(velocity, rectangleOne, rectangleTwo, dt)
if velocity.vx == 0 and velocity.vy == 0 then return 0 end
local expandedRectangle = {
x = rectangleTwo.x - rectangleOne.width / 2,
y = rectangleTwo.y - rectangleOne.height / 2,
width = rectangleTwo.width + rectangleOne.width,
height = rectangleTwo.height + rectangleOne.height
}
local ray = {
x = rectangleOne.x + rectangleOne.width / 2,
y = rectangleOne.y + rectangleOne.height / 2,
vx = velocity.vx * dt,
vy = velocity.vy * dt
}
local collision = rayVsRect(ray, expandedRectangle)
return collision
end
The way velocity is adjusted is handled by the hitbox component in my whole system. I don't need to include the whole thing, but an excerpt of how the velocity is adjusted will probably be helpful to think about as well.
local collision = {}
collision = rectVsRect(velocity, rectangleOne, rectangleTwo, dt)
if type(collision) ~= "table" then return end
if (collision.contactTime < 0) or (collision.contactTime >= 1) then return end
velocity.vx = velocity.vx + collision.contactNormal.x * math.abs(velocity.vx) * (1 - collision.contactTime)
velocity.vy = velocity.vy + collision.contactNormal.y * math.abs(velocity.vy) * (1 - collision.contactTime)
There are lots of things that could be the problem, and I'm having trouble narrowing it down and coming up with the right tests to figure it out. I feel like this sort of error, where there's nothing wrong syntactically but it doesn't behave quite how you want it to, is the hardest sort of error to figure out, but likely the most important to get good at solving.
These are the things that come to my mind of what it could be:
Some slight problem in the rayVsRect maths/logic, perhaps related to the "infinity" that comes about when dividing by 0. Now that I think about it, in this case the expanded rectangle's position might be the same as the ray's position in whatever direction it is, which would make math.sign(rectangle.x - ray.x) equal to 0. Maybe the subtlety is there? I'll investigate that pretty soon, but for now I don't know.
Something to do with expanding the rectangle in rectVsRect, maybe I did the math or logic slightly wrong? Compared to other's versions that I've learned this technique from though, it looks almost exactly the same as far as I can tell, and their versions work very nicely
Something to do with the resolution technique, although I really can't think of anything it could be
In summary, I'm not entirely sure what the problem is. The strongest lead seems to be my first bullet point, but I think I need help navigating this. I'm not really sure how to test it in either case. I like to think I'm good at coding/math, but things like this really make me feel small, and in ways that's a good thing. I'd like to overcome it, and learn how to be better at this, but I would also really appreciate help!
EDIT: So update after digging into the divide by zero thing. My suspicions lead me to investigate how the math worked out. I originally had to add a little if statement after calculating the near and far times in rayVsRect because a divide by zero would turn the values to nan. This caused the player rectangle to disappear because its transform wasn't a pair of numbers anymore. Normally I don't think this is a problem in a language like C++ (I learned this way of detection/resolution from someone who coded in C++), but it was a problem here in lua.
I was very suspicious of what happened when I used 'math.sign()`. I had to code in this function for this purpose and others, and it simply looks like this:
function math.sign(x)
if x < 0 then
return -1
elseif x > 0 then
return 1
else
return x
end
end
This seems fine and all, and it really is, but it was causing issues in the bit of code that turned nans into really large numbers. In any language that would produce an infinity instead of nan, that would be fine for rayVsRect because the comparison below would still yield the wanted results.
if (nearX > farY) or (nearY > farX) then return 0 end
My extra bit of code was supposed to turn the nans into a large number to simulate this same sort of math that works. However, the fact that math.sign() returns 0 when the input is 0 kind of messes things up.
When the ray's velocity and rectangle's side perfectly line up in any way, that creates one of these situations where 0 is returned from math.sign(). For example, if the velocity vector perfectly passes through the top side of the rectangle, math.sign(rectangle.y - ray.y) would give us 0. Then the snagging would occur, because 0 is undoubtedly less than whatever farX is (it's probably well over 1 at my player's speed).
I don't really know the most efficient way to adjust my code, and could perhaps use some help with that. I've thought about changing math.sign() but I think the way it works is fine, and I use it for other functions too. I've also thought about making a new math.sign() specifically for this, but I'm not sure how it would work. This is because each different situation needs either a positive 1 or negative 1, and there's no way math.signNewAndImproved() would be able to tell without clunkily passing it in.
I tried a slightly clunky solution by adding a couple of if statements. My code went from this:
--Turn nan values into "infinity"
if nearX ~= nearX then
nearX = 4294967296 * math.sign(rectangle.x - ray.x)
farX = 4294967296 * math.sign(rectangle.x + rectangle.width - ray.x)
end
if nearY ~= nearY then
nearY = 4294967296 * math.sign(rectangle.y - ray.y)
farY = 4294967296 * math.sign(rectangle.y + rectangle.height - ray.y)
end
To this:
--Turn nan values into "infinity"
if nearX ~= nearX then
nearX = 4294967296 * math.sign(rectangle.x - ray.x)
farX = 4294967296 * math.sign(rectangle.x + rectangle.width - ray.x)
if rectangle.x == ray.x then nearX = 4294967296 end
if (rectangle.x + rectangle.width) == ray.x then farX = -4294967296 end
end
if nearY ~= nearY then
nearY = 4294967296 * math.sign(rectangle.y - ray.y)
farY = 4294967296 * math.sign(rectangle.y + rectangle.height - ray.y)
if rectangle.y == ray.y then error(tostring(farY)) nearY = 4294967296 end
if (rectangle.y + rectangle.height) == ray.y then farY = -4294967296 end
end
However, I've run into a slightly different dilemma. This actually solved the problem for the top and left sides of the target rectangle, however it did pretty much nothing for the bottom and right sides of the rectangle. Why could this be? It must be a math error, I guess I'll have to figure it out!
The Humane Ai Pin was supposed to be the first in a new category of wearable, AI-first devices. But it arrived this year to universally awful reviews citing its limited functionality, spotty reliability, awful battery life, and high price, just to name a few problems. Last month we learned that Humane was looking to sell […]
This just started occurring and seems to randomly happen during, and between, game sessions. A dynamic moving body collides with a static body and instead of bouncing off looses (almost completely) its Velocity along the collision's normal. This means the dynamic body starts moving along the static body's surface it just collided with, and is most noticeable on the rare occasions it does a 90 degree turn upon hitting a second wall right ahead.
This behaviour is very erratic, and almost seems to come and go between builds with the same code on my content (although it could just be chance), so I'm wondering if it could be an issue with the cocos2d libraries?
For reference, the way I'm setting up these bodies:
I believe they are both set up correctly to achieve fully elastic collisions, and I'm sure this was working at some point through a slightly different flow (they didn't share the initial build code). Has anyone experienced any similar behaviour?
Bullies try to dominate negotiations through aggression, intimidation and unreasonable demands. But you don't have to feel powerless or let them push you around, write Stepbanie Vozza in her article for Fast Company, titles "How to negotiate with a bully." — Read the rest
The sheer number of computer monitors on the market is enough to intimidate anyone lookin to add one to their workspace or gaming rig. Plus, the technology has evolved rapidly even in just the past year alone with OLED Flex, QD-OLED and built-in smart platforms becoming more prevalent in new monitors. That’s on top of big improvements in things like color accuracy, image quality, size and resolution as well. But fear not, Engadget can help you make sense of the computer monitor space and help you decide which monitors (or, at the very least, type of monitor) is right for you. Whether you’re a business user, a content creator, a multitasker or into competitive gaming, you have plenty of options to choose from and we’ve outline our top picks below.
Factors to consider
Panel type
The cheapest monitors are still TN (twisted nematic), which are strictly for gamers or office use. VA (vertical alignment) monitors are also relatively cheap, while offering good brightness and a high contrast ratio. However, content creators will find that IPS (in-plane switching) LCD displays deliver better color accuracy, picture quality and viewing angles.
If maximum brightness is important, a quantum dot LCD display is the way to go — those are typically found in larger displays. OLED monitors are now available and offer the best blacks and color reproduction, but they lack the brightness of LED or quantum dot displays. Plus, they cost a lot. The latest type of OLED monitor, called QD-OLED from Samsung, just came out in 2022. The most notable advantage is that it can get a lot brighter, with monitors shown at CES 2022 hitting up to 1,000 nits of peak brightness.
MiniLEDs are now widely used in high-end displays. They’re similar to quantum dot tech, but as the name suggests, it uses smaller LED diodes that are just 0.2mm in diameter. As such, manufacturers can pack in up to three times more LEDs with more local dimming zones, delivering deeper blacks and better contrast.
Screen size, resolution and display format
In this day and age, screen size rules. Where 24-inch displays used to be more or less standard (and can still be useful for basic computing), 27-, 32-, 34- and even 42-inch displays have become popular for entertainment, content creation and even gaming these days.
Nearly every monitor used to be 16:9, but it’s now possible to find 16:10 and other more exotic display shapes. On the gaming and entertainment side, we’re also seeing curved and ultrawide monitors with aspect ratios like 21:9. If you do decide to buy an ultrawide display, however, keep in mind that a 30-inch 21:9 model is the same height as a 24-inch monitor, so you might end up with a smaller display than you expected. As a rule of thumb, add 25 percent to the size of a 21:9 monitor to get the vertical height you’d expect from a model with a 16:9 aspect ratio.
A 4K monitor is nearly a must for content creators, and some folks are even going for 5K or all the way up to 8K. Keep in mind, though, that you’ll need a pretty powerful computer to drive all those sharp pixels. And 4K resolution should be paired with a screen size of 27 inches and up, or you won’t notice much difference between 1440p. At the same time, I wouldn’t get a model larger than 27 inches unless it’s 4K, as you’ll start to see pixelation if you’re working up close to the display.
One new category to consider is portable monitors designed to be carried and used with laptops. Those typically come in 1080p resolutions and sizes from 13-15 inches. They usually have a lightweight kickstand-type support that folds up to keep things compact.
HDR
HDR is the buzzy monitor feature to have these days, as it adds vibrancy to entertainment and gaming – but be careful before jumping in. Some monitors that claim HDR on the marketing materials don’t even conform to a base standard. To be sure that a display at least meets minimum HDR specs, you’ll want to choose one with a DisplayHDR rating with each tier representing maximum brightness in nits.
However, the lowest DisplayHDR 400 and 500 tiers may disappoint you with a lack of brightness, washed out blacks and mediocre color reproduction. If you can afford it, the best monitor to choose is a model with DisplayHDR 600, 1000 or True Black 400, True Black 500 and True Black 600. The True Black settings are designed primarily for OLED models, with maximum black levels at .0005 nits.
Where televisions typically offer HDR10 and Dolby Vision or HDR10+, most PC monitors only support the HDR10 standard, other than a few (very expensive) models. That doesn’t matter much for content creation or gaming, but HDR streaming on Netflix, Amazon Prime Video and other services won’t look quite as punchy. In addition, the best gaming monitors are usually the ones supporting HDR600 (and up), rather than content creation monitors – with a few exceptions.
Refresh rate
Refresh rate is a key feature, particularly on gaming monitors. A bare minimum nowadays is 60Hz, and 80Hz and higher refresh rates are much easier on the eyes. However, most 4K displays top out at 60Hz with some rare exceptions and the HDMI 2.0 spec only supports 4K at 60Hz, so you’d need at least DisplayPort 1.4 (4K at 120Hz) or HDMI 2.1. The latter is now available on a number of monitors, particularly gaming displays. However, it’s only supported on the latest NVIDIA RTX 3000- and 4000-series, AMD RX 6000-series GPUs.
Inputs
There are essentially three types of modern display inputs: Thunderbolt, DisplayPort and HDMI. Most monitors built for PCs come with the latter two, while a select few (typically built for Macs) will use Thunderbolt. To add to the confusion, USB-C ports may be Thunderbolt 3 and by extension, DisplayPort compatible, so you may need a USB-C to Thunderbolt or DisplayPort cable adapter depending on your display.
Color bit depth
Serious content creators should consider a more costly 10-bit monitor that can display billions of colors. If budget is an issue, you can go for an 8-bit panel that can fake billions of colors via dithering (often spec’d as “8-bit + FRC”). For entertainment or business purposes, a regular 8-bit monitor that can display millions of colors will be fine.
Color gamut
The other aspect of color is the gamut. That expresses the range of colors that can be reproduced and not just the number of colors. Most good monitors these days can cover the sRGB and Rec.709 gamuts (designed for photos and video respectively). For more demanding work, though, you’ll want one that can reproduce more demanding modern gamuts like AdobeRGB, DCI-P3 and Rec.2020 gamuts, which encompass a wider range of colors. The latter two are often used for film projection and HDR, respectively.
Console gaming
Both the Xbox Series X and Sony’s PS5 can handle 4K 120Hz HDR gaming, so if you’re into resolution over pure speed, you’ll want a monitor that can keep up and provide the best gaming experience possible. 4K resolution, HDR and at least 120Hz is the minimum starting point, but fortunately there are 27-inch displays with those specs starting at well under $1,000.
Pricing and parts shortages
Though the pandemic has eased, monitor supply is still a bit tighter than pre-pandemic levels due to supply and demand issues. To that end, you may have trouble finding monitors at Amazon, B&H or elsewhere for the suggested retail price point. For our guide below, we’re basing our picks on the MSRP, as long as the street price doesn’t exceed that by more than $25.
Best monitors under $200
Best monitors under $400
Best monitors under $500
Best monitors under $1,000
This article originally appeared on Engadget at https://www.engadget.com/how-to-buy-a-monitor-143000069.html?src=rss
We are very excited to announce the release of AMD FidelityFX Super Resolution 3 (FSR 3) technology on GPUOpen, complete with full source code for DirectX 12 and Unreal Engine 5.