I'm new to Unity and to game development in general.
I would like to make a text-based game.
I'm looking to reproduce the behavior of an instant messenger like messenger or whatapp.
I made the choice to use the Unity UI system for the pre-made components like the rect scroll.
But this choice led me to the following problem:
I have "bubbles" of dialogs, which must be able to grow in width as well as in height with the size of the text. Fig.1
I immediately tried to use VectorGraphics to import .svg with the idea to move runtime the points of my curves of Beziers.
But I did not find how to access these points and edit them runtime.
I then found the "Sprite shapes" but they are not part of the "UI",
so if I went with such a solution, I would have to reimplement
scroll, buttons etc...
I thought of cutting my speech bubble in 7 parts Fig.2 and scaling it according to the text size. But I have the feeling that this is very heavy for not much.
Finally I wonder if a hybrid solution would not be the best, use the
UI for scrolling, get transforms and inject them into Shape sprites
(outside the Canvas).
If it is possible to do 1. and then I would be very grateful for an example.
If not 2. 3. 4. seem feasible, I would like to have your opinion on the most relevant of the 3.
Thanks in advance.
There is a simpler and quite elegant solution to your problem that uses nothing but the sprite itself (or rather the design of the sprite).
Take a look at 9-slicing Sprites from the official unity documentation.
With the Sprite Editor you can create borders around the "core" of your speech bubble. Since these speech bubbles are usually colored in a single color and contain nothing else, the ImageType: Sliced would be the perfect solution for what you have in mind. I've created a small Example Sprite to explain in more detail how to approach this:
The sprite itself is 512 pixels wide and 512 pixels high. Each of the cubes missing from the edges is 8x8 pixels, so the top, bottom, and left borders are 3x8=24 pixels deep. The right side has an extra 16 pixels of space to represent a small "tail" on the bubble (bottom right corner). So, we have 4 borders: top=24, bottom=24, left=24 and right=40 pixels. After importing such a sprite, we just have to set its MeshType to FullRect, click Apply and set the 4 borders using the Sprite Editor (don't forget to Apply them too). The last thing to do is to use the sprite in an Image Component on the Canvas and set the ImageType of this Component to Sliced. Now you can scale/warp the Image as much as you like - the border will always keep its original size without deforming. And since your bubble has a solid "core", the Sliced option will stretch this core unnoticed.
Edit: When scaling the Image you must use its Width and Height instead of the (1,1,1)-based Scale, because the Scale might still distort your Image. Also, here is another screenshot showing the results in different sizes.
Related
I need to move an image down through canvas so that its central point would be where is now its top edge. It makes some 50 points, but if I decrease y by 50, it moves to different part of the screen on devices with different screen size. I guess, it's because my main canvas is set to scale with the screen size. So I suppose I need to manually divide the number 50 by my screen height and then code to multiply by Screen.height? Isn't there a more convenient way to move UI objects?
Allow me a second question: Do you think it is even wise to make a game purely on canvas? My game is simple 2D, only slightly animated and contains many layout elements, so I decided to go for it, but I have hard time to grasp the UI position rules.
you may have the problem of the anchoring.
Unity UI totally depends on the Anchoring, if you have got right anchoring there is no issue.
For example. if you anchored something at the Center than changing left and right value moves them according to the center anchor.
for clear visualization, you can paste a screenshot of the behavior.
I wonder is there any way to slice this sprite(dialog pop up thing) that could keep the bottom center (the upside-down triangle) not scaled? I'm using nGUI if it matters.
Nope
Sorry, but that's how 9-slice scaling works. You would need 25 slice scaling to do what you're looking for and that's overkill for most things, so I've never seen an implementation.
What to do instead...
Break up your sprite into two pieces: the 9-slice portion and the "notch" portion. Then just position the notch to be in the right place.
I haven't used nGUI (only iGUI and the Unity native--both old and new) so I'm not sure on the precise nature of how nGUI will let you do that, but you'd still need two sprites, one of which is scaled and the other one which isn't, positioned either manually or through parent-child relative relationship. If your dialog is always the same width, it'll be pretty straight forward. If not, it might be more challenging.
A few other things:
You'll probably want the notch sprite and the bubble sprite to the same native image size, but its not necessary (might make things easier, might not).
The notch will want to have some "overbleed" so that when the two stack the underlying rendering code doesn't go all squinty eyed and go "there's a gap here..." and draw through in some cases.
Depending on the bubble portion's drawn edge, you might want the notch to be in front or behind. In your precise case, I don't think it'll make a difference. It's a little hard to tell due to the colors, but when I did a selectable tab (which is built similarly), the tab sits on top of the container window so that the shaded edge flows nicely. The unselected version then has no overbleed so it looks like it sits "behind" (accurate pixel placement--2D game at a fixed size--insures that no "gap" is rendered).
It's a little tedious but pretty straightforward to implement this for UI images. I recently did it in order to make a slice stretch the left/right borders of a 9-slice instead of the center.
The trick is to subclass Image and override OnPopulateMesh, where you do the calculations you need and set positions/uvs to whatever you require.
Here's a helpful how-to article: https://www.hallgrimgames.com/blog/2018/11/25/custom-unity-ui-meshes
Things for a non-UI sprite will be harder. I think you'll have to create all your geometry in a script, and the calculations might be a little complicated because you're using an atlas.
I've been searching around for this one for a bit, and unfortunately I can't seem to find any good, consistent results. So, in the Unity UI system, buttons can stretch without becoming pixelated or distorted. This is because the texture is split up into 9 parts - the corners, middle, and sides.
This works because the button's middle and sides are stretched, but not the corners. Then, the button appears not pixelated, at any dimension.
So, the question is as follows: How can I do the same thing for a transparent, unlit texture in 3D space? I have a speech bubble texture on a flat plane that I know how to re-scale to fit the text in the speech bubble.
I've set the texture type to Multiple Sprite, and divided it up into 9 parts. However, I cannot seem to find where I can set the texture to act like the UI button does, and I'm not sure that this is even possible in this way in 3D space.
Is there a way, or should I just make the different parts of the texture different objects, and move them together? That would seem very inefficient and ugly compared to this.
To accomplish what you are asking, you would need to create tiles for this speech bubble and then write a script that procedurally builds a speech bubble based on the plane's scale value. You could also try just changing the texture's Filter Mode to Point.
However I really don't think you should be using textures for this anyway. Why not just use a Unity Canvas and set the Render Mode to World Space? Then you can just set your text box to be a sprite, not a texture, and set its filter mode to Point (See below). This would also make it a lot easier for when you want there to be text in the speech bubble later on.
I'm investigating the feasibility of using Raphael for a user-research project. One of the features allows for users to drag images onto a canvas and we record where they placed it. The pool of images is potentially quite large and we'll have them in a scrollable box in the tool.
I put together a quick wireframe of the issue I'm looking into since it'll probably be clearer than my explanation.
Please see the wireframe:
I'd stick with straight HTML/CSS and use jQueryUI draggables, as you mention in your comment.
You don't appear to need any of the drawing/display features SVG offers, yet if you went that route, you'd have to build your own custom scrolling behavior (instead of setting a CSS overflow-y rule) and picture layout algorithms (again instead of using CSS floats or something).
You can create a scrollable region using Raphael.
Create the viewport with fixed
dimensions (say 800x600)
Draw the images with increasing y value. After few images, the y value will go beyond 600. It will be drawn but will not be visible in the viewport.
Create a scrollbar using raphael rects. Attach drag events to the scrollbar handle rect.
When the handle is moved, translate all the images accordingly.
For e.g. lets assume in step 2, you had drawn all the images and the bottom most point of the end image is having y value 2000. Assuming the scrollbar has length 500, each dx movement of the handle will have to translate 2000/500 = 4dx. You can calculate the handle length similarly using ratios.
Since everything inside a single Raphael paper the dragging of images will work seamlessly. You will have to maintain the positions of each images.
You might find this demo similar
Remember you can always use getBBox when you drop. In this case it's rects but images would be the same..
http://irunmywebsite.com/raphael/additionalhelp.php?q=bearbones
I am adding some functionality to an iPhone app, and could use some help in picking the fastest / most efficient / best practice approach for solving this problem:
At the upper-half of my screen, I have speech bubbles (think comic book) that are UIImageViews translating across the screen (dynamic x & y position). It is a UIImageView because there is an image as the background of the speech bubble.
Each speech bubble has a matching image moving around the bottom of the screen (elsewhere in the layer tree)
I would like to draw a tail (that triangle bit from a speech bubble) so the point of the triangle is tracking the lower image, with the base of the triangle being attached to the bottom of the upper UIImageView. (technically the base doesn't have to be butted against, it can overlap as long as I can match the color of my background image to the triangle).
I have already done all the tracking & drawn a line with CGContextStrokePath methods, and now I am stuck on how to replace the line with a triangle.
I have looked at drawing a triangle in Quartz and filling it. My concern is the speech bubbles are repositioned every 1/10th of a second, and it looks like drawing just the line used for proof of concept had a pretty severe performance / visual smoothness impact.
One idea I have is to do the trigonometry myself, and stretch & rotate an image of a triangle to connect each of these speech bubbles with the lower spot. Something is telling me there is a more efficient / more elegant solution, but I am not able to see it looking through the documentation. Any help on how you have or would approach this issue is appreciated. Thanks.
If the speech bubbles are fixed in size, just use a static UIImage. Set the image view's layer.position property at the point of the triangle. Then you can use view animation to move the bubbles around.
If you need the speech bubbles to be different sizes, I'd create a resizeable image using resizableImageWithCapInsets. Then I'd do the same as above to position it.
If there was something special about the speech bubble that I could't achieve with either a static image or a resizable image, I'd probably create a custom CA Layer or layers to get the effect I wanted (Like a gradient layer with a shape layer as it's mask layer)