text:
Unlimited AE and Premiere Pro templates, videos & more! Unlimited asset downloads! From $16.50/m Advertisement # The Benefits of Wide Aperture (And Choosing a Lens for Under$500)

Read Time:9 minsLanguages:
This post is part of a series called Lenses.
Introducing the Wonderful World of 50mm Prime Lenses

Today we'll look at a few of the benefits of shooting with a wide aperture. If you're new to photography there will be some key insight here into one of the biggest factors for taking professional quality photos that will stun your friends and family. After this, we'll take a look at several lenses that will help you get to f/2.0 and wider without forcing you to give up food and electricity for the next six months to make the purchase!

## Why Don't My Photos Look Amazing?

So you finally decided to get serious about photography and went out and bought a new camera. If you're like most beginners, you picked up something high quality but affordable like a Canon Rebel or Nikon D80.

These types of cameras often come with a basic "kit lens." In the case of my own Rebel T1i, the kit lens was an 18-55mm f/3.5-5.6. I want to be clear that there's absolutely nothing wrong with shooting with this lens. It's versatile and can be used in a number of different situations containing varying lighting and distance factors.

However, you've probably noticed that the photos, in particular the portraits, you've been taking with your kit lens are good, but not great. They're far better than what you could get with a cell phone or flash and trash camera from the drug store, but not quite something that you could make a living selling.

As an example, consider the image below.

This is a nice shot. It's cute, engaging, bright and crisp. However, the subject doesn't quite pop the way you see in many professional portraits.

Now consider this next image:

There's something fundamentally different about this image isn't there? Something that immediately makes it seem high quality and professional. Something beyond the closer crop and even the lighting in the scene.

The answer is completely obvious to some but remains somewhat elusive to others. In case you missed it, it's the background. In the first image, the background is slightly blurred, but is still perfectly decipherable and therefore demands much of your attention. The house in this shot detracts from the main subject, which is of course the boy. It's not that the house is ugly or uncommonly busy, just that it's in-focus enough to make your brain feel like it's an important part of the composition.

In the second image, the background has been blurred out so much that it's actually difficult to even decipher what's going on back there. This causes your brain to interpret this space very differently than the sharper space in the foreground. By mimicking the way your eyes focus, this shot creates the subtle illusion of depth in a two-dimensional image.

## Depth Of Field

The term used to describe the primary difference between the two images above is "depth of field." Put simply, images with a shallow depth of field (like the second photograph) have very little in-focus while images with a greater depth of field (like the first photograph) are in-focus over a much great area.

You can manipulate the depth of field in your photographs by adjusting your aperture. A wider aperture produces a shallower depth of field and a narrow aperture produces greater depth of field. As an example, consider the spliced image below. According to the photographer, the left portion was shot at f/29 and the right portion at f/4.5.

As you can clearly see, the background gets much blurrier as the aperture widens (the lower the number, the wider the hole that lets in light will be).

## Shooting in Low Light

Perhaps even more of an issue for many photographers is the need to shoot in poor lighting conditions. Whether you're getting paid to photograph a wedding in a dark church or just want to take some nice indoor shots of your family on Thanksgiving, a lens that can grab a lot of light is a necessity.

Obviously, a flash is mounted on your camera for this very purpose. However, built-in flashes tend to be quite harsh if not diffused properly. You can and should invest in portable lighting equipment, but there are still plenty of opportunities where you either won't want to or won't be allowed to use a flash.

One of the benefits of a lens with a wide aperture is that it can collect a ton of light. If you've ever shot during sunset as the available light is decreasing, you know that there are plenty of times when you need to capture every photon you possibly can!

In these instances, the shallow depth of field again has an impact. Just be sure to zoom in and take a look at your photos to make sure the important parts of the image are staying crisp. If you're shooting people, it's a good rule of thumb to focus on the eyes.

## Can I Afford A Good Lens?

After reading the information above, you're probably ready to grab your camera, blast open your aperture and go to town. The trick is, every lens has its limit for just how wide the aperture can go. As I stated above, the kit lens that comes with a Rebel T1i tops out at f/3.5. This is fine for many purposes but definitely not ideal for capturing blurry, rich-bokeh backgrounds.

## The Thrifty Fifty

If you're really set on achieving a fairly wide aperture but don't really have much money to burn, look no further than the Canon EF 50mm f/1.8 II, also lovingly referred to by many photographers as the "thrifty fifty."

Short of a pirated copy of Photoshop and the Lens Blur filter, this is by far the cheapest way for Canon users to achieve nice blurry backgrounds in their photos (around $100 brand new). This lens produces beautifully crisp images with decent (but not great) color and is as compact and light as any lens you'll find. The downside is that the construction mirrors the price. It's a fairly cheap feeling lens comprised mostly of plastic. Further, many users report that the less than optimal five aperture blades tend to produce relatively poor bokeh. Still, at a hundred bucks it's definitely not a bad place to start. ## AF NIKKOR 50mm f/1.8D The Nikon users out there definitely have an excellent answer to the Canon 50mm f/1.8 in the Nikkor equivalent. It's a very similar lens in all respects to the Canon version. The construction is mostly plastic, making it feeling cheap but also super lightweight. Further, the autofocus is super fast and critics rave on the surprising crispness of the image quality for a lens so affordable. If you're a hobbyist and don't really see yourself ever making money from photography this is a perfect first lens purchase. ## Canon EF 50mm f/1.4 USM Canon's next step up takes a rather large leap in price up to$389 (if you look around, it's fairly easy to find in the $350 range). I own this lens and simply can't say enough about it. In fact, it was used for the image of the woman above. The images are crystal clear, the construction feels solid, there are eight aperture blades instead of five, and it's still really small and lightweight, though obviously not quite as much as the 1.8 above. I was initially worried about the lack of a zoom, but I found that I really like the 50mm prime because it makes focusing much faster. It's a perfect zoom for shooting what you see and it's occasionally nice to have one less variable to worry about. The USM (Ultrasonic Motor) is much quieter than my kit lens, but not quite as quiet as I was hoping it would be. I've used some of the pricier Canon USM lenses that were ridiculously smooth and the 50mm f/1.4 certainly falls well beneath these. Tons of photographers all over the web agree with me that this lens is really an excellent buy for anyone with a low to mid-range budget. If you can afford to choose this option over the thrifty fifty, go with it and never look back. ## AF NIKKOR 50mm f/1.4D All of the conclusions drawn for the jump from the Canon f/1.8 to the f/1.4 apply here as well. If you're really strapped for cash, go with the f/1.8, but if you can scrounge up the extra couple hundred bucks, absolutely go with the f/1.4 instead. The leap from 1.8 to 1.4 might not sound like much, but when you're shooting low light, you'll never be sorry you spent the extra money. This lens is extremely fast and produces images that are sharp enough to rival lenses three times its price. As far as I can tell, you'll be every bit as happy with this lens as I am with my Canon 1.4. ## More Lenses Under$500

Due to their affordability, the selections above represent my suggestions for where to start your search. However, for $500, you can find several more outstanding lenses even higher in quality than those we've already seen. Here are a few to check out: #### Canon EF 85mm f/1.8 USM #### AF-S NIKKOR 50mm f/1.4G #### Canon EF 100mm f/2 USM #### AF NIKKOR 85mm f/1.8D ## What's Your Favorite Lens? I hope this article has helped make the decision for your next lens purchase a little easier. Keep in mind that the lenses above are straight from Canon and Nikon and that even more affordable alternatives can often be found from other manufacturers such as Sigma and Vivitar. Leave a comment below and let us know your recommendations for a good lens below$500. Tell us about that one affordable but high quality lens that you simply couldn't be without and why.

Advertisement
Did you find this post useful?
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.

format: plain


text:
# Return on Investment (ROI)

In finance, the Return on Investment (ROI) is an estimated measure of the profitability of an investment by measuring the amount of return on the given investment relative to the investment’s cost.

This is typically calculated by dividing the investment’s return by its cost, hence producing a ratio.

$ROI = \frac{V-C}{C},$

where $$V$$ is the investment’s current value, and $$C$$ is the investment’s cost.

### Notes mentioning this note

There are no notes linking to this note.

Here are all the zettels in this zettelkasten, along with their links, visualized as a graph. You may need to zoom and pan around to see something.


text:
# IBMPopSim v0.3.0

0

0th

Percentile

## Individual Based Model Population Simulation

Simulation of the random evolution of structured population dynamics, called stochastic Individual Based Models (IBMs) (see e.g. Ferri<c3><a8>re and Tran (2009) <doi:10.1051/proc/2009033>, Bansaye and M<c3><a9>l<c3><a9>ard (2015) <doi:10.1007/978-3-319-21711-6>, Boumezoued (2016)). The package allows users to simulate the random evolution of a population in which individuals are characterised by their date of birth, a set of attributes, and their potential date of death.

# IBMPopSim

The IBMPopSim package aims at simulating the random evolution of heterogeneous populations, called stochastic Individual Based Models (IBMs). Such models have a wide range of applications in various fields including actuarial sciences, biology, demography, or ecology. For instance, IBMs can be used for simulating the evolution of an heterogeneous insurance portfolio, of an spatial ecological population with interacting individuals, or for validation mortality forecasts.

The package allows users to simulate population evolution in which individuals are characterized by their age and some characteristics, and where the population is modified by different types of events including births/arrivals, death/exit events, or changes of characteristics. The frequency at which an event can occur to an individual can depend on his age and characteristics, but also on time and on the rest of the population (interactions).

IBMPopSim overcomes the limitations of time consuming IBMs simulations. This is done by implementing new efficient algorithms based on thinning methods, which are compiled using the Rcpp library. The package allows a wide range of IMBs to be simulated, while being user-friendly thanks to its structure based on simple build blocks. In addition, we provide tools for analyzing outputs, such a age-pyramids or life tables obtained from the simulated data, consistent with the data format of packages for mortality modeling such as StMoMo. See vignette(IBMPopSim) for more details.

## Installation

The latest stable version can be installed from CRAN:

install.packages('IBMPopSim')

The latest development version can be installed from github:

# install.packages("devtools")
devtools::install_github('DaphneGiorgi/IBMPopSim')

### First example to check installation

To illustrate the use of the package and to check the installation, a simple model with Poisson arrivals and exits is implemented.

library(IBMPopSim)

init_size <- 100000
pop <- data.frame(birth = rep(0, init_size), death = NA)

birth = mk_event_poisson(type = 'birth', intensity = 'lambda')
death = mk_event_poisson(type = 'death', intensity = 'mu')
params = list('lambda' = 100, 'mu' = 100)

# mk_model compiles C++ code using sourceCpp from Rcpp
birth_death <- mk_model(events = list(birth, death),
parameters = params)

If there are no errors then the C++ built environment is compatible with the package. The model is created and a C++ code has been compiled. The simulation is done using the popsim function.

sim_out <- popsim(model = birth_death,
population = pop,
events_bounds = c('birth' = params$lambda, 'death' = params$mu),
parameters = params,
time = 10)
## Simulation on  [0, 10]

num_births <- length(sim_out$population$birth) - init_size
num_deaths <- sum(!is.na(sim_out$population$death))
print(c("births" = num_births, "deaths" = num_deaths))
## births deaths
##    952    981

## Quick model creation

• We take here an initial population, stored in a data frame, composed of 100 000 individuals marked by their gender (encoded by a Boolean characteristic):
pop <- EW_pop_14$sample  • The second step is to define the model parameters’ list: params <- list("alpha" = 0.008, "beta" = 0.02, "p_male" = 0.51, "birth_rate" = stepfun(c(15,40), c(0,0.05,0)))  • The last step is to defined the events that can occur in the population, here birth and death events: death_event <- mk_event_individual(type = "death", intensity_code = "result = alpha * exp(beta * age(I, t));") birth_event <- mk_event_individual(type = "birth", intensity_code = "result = birth_rate(age(I,t));", kernel_code = "newI.male = CUnif(0, 1) < p_male;")  Note that these events contain some C++ statements that depend (implicitly) on the previously declared parameters in variable params. • Finally, the model is created by calling the function mk_model. A C++ source code is obtained from the events and parameters, then compiled using the sourceCpp function of the Rcpp package. model <- mk_model(characteristics = get_characteristics(pop), events = list(death_event, birth_event), parameters = params)  • In order to simulate a random trajectory of the population until a given time T bounds on the events intensities have to be specified: a_max <- 115 events_bounds = c("death" = params$alpha * exp(params$beta * a_max), "birth" = max(params$birth_rate))

Then, the function popsim can be called:

sim_out <- popsim(model, pop, events_bounds, params,
age_max = a_max, time = 30)
## Simulation on  [0, 30]

• The data frame sim_out$population contains the information (date of birth, date of death, gender) on individuals who lived in the population over the period [0, 30]. Functions of the package allows to provide aggregated information on the population. pop_out <- sim_out$population
##       birth death  male
## 1 -84.96043    NA FALSE
## 2 -84.86327    NA FALSE
## 3 -84.84161    NA FALSE
## 4 -84.79779    NA FALSE
## 5 -84.76461    NA FALSE
## 6 -84.76363    NA FALSE
female_pop <- pop_out[pop_out$male==FALSE, ] age_pyramid(female_pop, ages = 85:90, time = 30) ## age male value ## 1 85 - 86 FALSE 224 ## 2 86 - 87 FALSE 250 ## 3 87 - 88 FALSE 213 ## 4 88 - 89 FALSE 170 ## 5 89 - 90 FALSE 180 Dxt <- death_table(female_pop, ages = 85:90, period = 20:30) Ext <- exposure_table(female_pop, ages = 85:90, period = 20:30)  • Note that parameters of the model can be changed without recompiling the model. params$beta <- 0.01

# Update death event bound:
events_bounds["death"] <- params$alpha * exp(params$beta * a_max)

sim_out <- popsim(model, pop, events_bounds, params,
age_max = a_max, time = 30)

## Functions in IBMPopSim

 Name Description mk_parameters_types Extract types (R and C++) of the parameters mk_event_individual Creates an event with intensity of class individual. merge_pop_withid A function returning a merged dataframe from a list of population dataframes with id. mk_event_poisson Creates Poisson class event. piecewise_xy Piecewise real function of two variables. plot_population Plot the age pyramid of a population data frame (at a given time). mk_model Creates a model for IBMPopSim. weibull Weibull function. mk_event_inhomogeneous_poisson Creates inhomogeneous Poisson class event. plot_pyramid Plot an age pyramid from age pyramid data frame. mk_event_interaction Creates an event with intensity of type interaction. linfun Linear interpolation function. piecewise_x Piecewise real function. popsample Sample a population from an age pyramid (at a given time). stepfun Step Function. max.stepfun Returns the maximum of a function of class stepfun. summary.event Summary of an event. popsim Simulation of a model. population_alive Returns a population of individuals alive. exposure_table Creates an exposure table. toy_params Toy parameters for IBMPopSim-human_popIMD vignette example. summary.model Summary of a model. get_characteristics Returns names and C types of the characteristics. EW_pop_14 England and Wales (EW) 2014 population, death and birth rates. age_pyramids Age pyramid from a population data frame at some given times. death_table Creates a death table. gompertz GompertzMakeham intensity function. age_pyramid Age pyramid from a population data frame at a given time. EW_pop_out Example of "human population" after 100 years of simulation. EW_popIMD_14 England and Wales (EW) 2014 population and death rates by Index of Multiple Deprivation (IMD). EWdata_hmd England and Wale mortality data (source: Human Mortality Database) No Results!

## Vignettes of IBMPopSim

 Name IBMPopSim.Rmd IBMPopSim.Rmd.orig IBMPopSim.bib IBMPopSim_cpp.Rmd IBMPopSim_cpp.Rmd.orig IBMPopSim_human_pop.Rmd IBMPopSim_human_pop.Rmd.orig IBMPopSim_human_pop_IMD.Rmd IBMPopSim_human_pop_IMD.Rmd.orig IBMPopSim_insurance_portfolio.Rmd IBMPopSim_insurance_portfolio.Rmd.orig IBMPopSim_interaction.Rmd IBMPopSim_interaction.Rmd.orig hpIMD_birth_intensities-1.pdf hpIMD_compo_fem-1.pdf hpIMD_compo_fem2-1.pdf hpIMD_compo_fem2-2.pdf hpIMD_death_rate-1.pdf hpIMD_df-1.pdf hpIMD_pyramids-1.pdf hpIMD_pyramids-2.pdf hp_birth_distrib-1.pdf hp_death_rate_1-1.pdf hp_intensities-1.pdf hp_log_death-1.pdf hp_pop_init-1.pdf hp_pop_init_1e6-1.pdf hp_pyramid_50-1.pdf hp_pyramids-1.pdf hp_pyramids2-1.pdf insur_LeeCarter_risk1-1.pdf insur_cohort-1.pdf insur_evol_mortality-1.pdf insur_forecast-1.pdf insur_mortality_rates-1.pdf insur_pyr_group-1.pdf insur_pyramid-1.pdf inter_output-1.png inter_output2-1.png inter_output3-1.png inter_pyramid-1.png main_plot_30-1.pdf main_prob_subgroup1-1.pdf plot_piecewise-1.pdf plot_stepfun-1.pdf precompile.R No Results!


text:
# Angular acceleration of a rod about different points [closed]

1)Suppose a rod is hinged, such that it is free to rotate about one of its edges. Now, the rod rotates with an angular acceleration α under the influence of a force F applied on the other end. We can find out α easily with the torque equation (Given that mass & length of rod is m & L). Now in this condition, if we apply torque equation on the COM of the rod, the angular acceleration that we have here is same.

Note: $F_1$ & $F_2$ are the forces provided by the hinges.

2) Now almost the same case, the only difference is that now, the force ‘F’ is acting on the COM, and we’ve to find angular acceleration of the rod about a)hinges b)the other end.

Why is the angular acceleration different? Doesn’t it has to be the same?

## closed as off-topic by Emilio Pisanty, Kyle Kanos, Jon Custer, stafusa, ZeroTheHeroJul 8 '18 at 2:59

This question appears to be off-topic. The users who voted to close gave this specific reason:

• "Homework-like questions should ask about a specific physics concept and show some effort to work through the problem. We want our questions to be useful to the broader community, and to future users. See our meta site for more guidance on how to edit your question to make it better" – Emilio Pisanty, Kyle Kanos, Jon Custer, stafusa, ZeroTheHero
If this question can be reworded to fit the rules in the help center, please edit the question.

• Hi, welcome to Physics SE! Please don't post formulae as pictures, but use MathJax instead. MathJax is easy for people on all devices to read, and can show up clearer on different screen sizes and resolutions. – user191954 Jul 5 '18 at 6:02
• Also, please note that check-my-work questions are generally considered off-topic here. We intend our questions to be potentially useful to a broader set of users than just the one asking, and prefer conceptual questions. Can you try making a question about some concepts that you'd need to solve this problem? – user191954 Jul 5 '18 at 6:24


text:
Calculate the pH of a solution of 0.10 M HF that is also 0.15 M HCN if K_a for HF is 1.0xx10^-5 and K_a for HCN is 1.0xx10^-7?

Jun 28, 2018

$\text{pH} \approx 2.09$

In principle, it does not matter much which acid you allow to go first, as long as the smaller ${K}_{a}$ is smaller by at least ${10}^{3}$. You may want to try this in reverse order, doing $\text{HCN}$ first and $\text{HF}$ second, just to see if you get about the same $\text{pH}$ again.

(You should get $x = 9.64 \times {10}^{- 6} \text{M}$ for $\left[{\text{H"_3"O}}^{+}\right]$ from $\text{HCN}$ going first, and $x \approx \text{0.00812 M}$ for $\text{HF}$ going second. However, when $\text{HF}$ goes, the small $x$ approximation can only be done with $\text{0.10 M}$, and you can say that $9.64 \times {10}^{- 6}$ $\text{<<}$ $x$ instead in this case.)

Also, a common pitfall is to forget about the ${\text{H"_3"O}}^{+}$ contributed by the acid that goes first. That should be included in the initial concentration of ${\text{H"_3"O}}^{+}$ for the acid that goes second, because they suppress each other.

Since these are both weak acids that "have" similar ${K}_{a}$ values, the weaker one ($\text{HCN}$) is not supposed to be ignored. But these ${K}_{a}$ values are not correct...

${K}_{a} \left(\text{HF}\right) = 6.6 \times {10}^{- 4}$
${K}_{a} \left(\text{HCN}\right) = 6.2 \times {10}^{- 10}$

So, we'd "have" to do sequential ICE tables, but we should not have to for this problem. We SHOULD be able to just ignore $\text{HCN}$...

For $\text{HF}$:

${\text{HF"(aq) + "H"_2"O"(l) rightleftharpoons "F"^(-)(aq) + "H"_3"O}}^{+} \left(a q\right)$

$\text{I"" "0.10" "" "" "-" "" "0" "" "" "" } 0$
$\text{C"" "-x" "" "" "-" "+x" "" "" } + x$
$\text{E"" "0.10-x" "-" "" "x" "" "" "" } x$

Therefore, using its ${K}_{a}$ (which is actually $6.6 \times {10}^{- 4}$):

$6.6 \times {10}^{- 4} = \left(\left[\text{F"^(-)]["H"_3"O"^(+)])/(["HF}\right]\right)$

$= {x}^{2} / \left(0.10 - x\right)$

We do the small $x$ approximation because that was the intent of the problem, and:

$6.6 \times {10}^{- 4} \approx {x}^{2} / 0.10$

=> x = sqrt(0.10 cdot6.6 xx 10^(-4)) = "0.00812 M" = ["H"_3"O"^(+)]_("HF")

(the true answer was $\text{0.00780 M}$, 4.15% error, which is just within range of good enough.)

That concentration becomes the initial in the next ICE table, which we will find does not change much at all.

For $\text{HCN}$ after $\text{HF}$:

${\text{HCN"(aq) + "H"_2"O"(l) rightleftharpoons "CN"^(-)(aq) + "H"_3"O}}^{+} \left(a q\right)$

$\text{I"" "0.15" "" "" "-" "" "" "0" "" "" "" } 0.00812$
$\text{C"" "-x" "" "" "-" "" "+x" "" "" } + x$
$\text{E"" "0.15-x" "-" "" "" "x" "" "" "" } 0.00812 + x$

For this ${K}_{a}$ (which is actually $6.2 \times {10}^{- 10}$):

$6.2 \times {10}^{- 10} = \left(\left[\text{CN"^(-)]["H"_3"O"^(+)])/(["HCN}\right]\right)$

$= \frac{x \left(0.00812 + x\right)}{0.15 - x}$

Here we see that $6.2 \times {10}^{- 10}$ $\text{<<}$ $0.00812$, or $8.12 \times {10}^{- 3}$, as well as $0.15$.

Therefore, in the presence of $\text{HF}$:

$6.2 \times {10}^{- 10} = \frac{x \left(0.00812\right)}{0.15}$

$= 0.0541 x$

=> x = 1.15 xx 10^(-8) "M" = ["H"_3"O"^(+)]_("HCN")

As a result, the total $\left[{\text{H"_3"O}}^{+}\right]$ would be:

color(blue)(["H"_3"O"^(+)]) = ["H"_3"O"^(+)]_("HF") + ["H"_3"O"^(+)]_("HCN")

= "0.00812 M" + 1.15 xx 10^(-8) "M" ~~ color(blue)("0.00812 M")

(Clearly, nothing much changed, because $\text{HCN}$ is a much weaker acid in reality, by a factor of about $1000000$.)

That makes the $\boldsymbol{\text{pH}}$:

$\textcolor{b l u e}{\text{pH} = - \log \left(0.00812\right) = 2.09}$


text:
# Explicit forms for the roots of Eulerian polynomials

Let $E_n(z)$ be the Eulerian polynomial $$E_n(z) = \sum_{\tau \in \mathfrak{S}_n} z^{\operatorname{des}(\tau)}$$ where $\mathfrak{S}_n$ denotes the set of all permutations of $\{1,\ldots,n\}$ and $\operatorname{des}(\tau)$ is the number of descents $\tau(i) > \tau(i+1)$ in the permutation $\tau$. These are studied in great detail, see its OEIS wiki page for other definitions and several properties. In particular, it is known the Eulerian polynomial has only negative and simple roots, $$E_n(z) = \prod_{i=1}^n (z+q^{(n)}_i)$$ for different positive numbers $q^{(n)}_i$.

My question now is

What is known about the $q^{(n)}_i$'s? Do they have an explicit description?

(It is known that the roots of $E_n$ separate the roots of $E_{n+1}$. This is, $$q_1^{(n+1)} < q_1^{(n)} < \cdots < q_{n}^{(n+1)}< q_n^{(n)} < q_{n+1}^{(n+1)}$$ when they come in sorted order. That's not the type of property I am looking for, but only properties towards their explicit values.)

Here are the first two examples and the type of property I would like to have answered from a description I search for:

\begin{align*} E_2(z) &= z^2 + 4z + 1 = (z+2-\sqrt{3})(z+2+\sqrt{3}) \\ E_3(z) &= z^3 + 11z^2 + 11z + 1 = (z+5+2\sqrt{6})(z+5-2\sqrt{6})(z+1) \end{align*}

(The roots become more complicated than $a\pm b\sqrt{c}$ for bigger $n$'s.)

It is known that the mean value of the discrete distribution given by $E_n$ is $n/2$ and the variance is $(n+2)/12$. This can be used to show that \begin{align*} \sum_i \frac{1}{1+q^{(n)}_i} &= \frac{n}{2} \\ \sum_i \frac{q^{(n)}_i}{\big(1+q^{(n)}_i\big)^2} &= \frac{n+2}{12} \end{align*}

Doing this computation in the first example yields $$\frac{1}{1+2+\sqrt{3}} + \frac{1}{1+2-\sqrt{3}} = 1$$ and $$\frac{2+\sqrt{3}}{(1+2+\sqrt{3})^2} + \frac{2-\sqrt{3}}{(1+2-\sqrt{3})^2} = \frac{1}{3}$$

Is there any known immediate property of the roots that can be used to get these identities?

• As for the roots having an explicit description, if the Galois group of $E_n(z)$ were abelian then there would be a trigonometric formula for the roots. However, this is not the case. It is known that $E_n(z)$ is irreducible. By the symmetry of the coefficients, the largest possible Galois group has order $2^m m!$, where $m=\lfloor n/2\rfloor$ (and is the hyperoctahedral group $B_m$) . It has been checked for $n\leq 9$ that $B_m$ is indeed the Galois group of $E_n(z)$, so one could conjecture that this is the case for all $n$. – Richard Stanley Dec 4 '17 at 17:02
• I was mistaken when I said that it is known that $E_n(z)$ is irreducible. First, $E_{2m}(z)$ is divisible by $1+z$. It is only conjectured that $E_{2m+1}(z)$ and $E_{2m}(z)/(1+z)$ are irreducible. For some instances of irreducibility see ac.els-cdn.com/0022314X84900507/…. – Richard Stanley Dec 6 '17 at 3:43

## 1 Answer

Here is some partial information. If $E_n(z)=\sum A_n(i)x^i$, then $A_n(i)$ grows roughly like $(i+1)^n$ for fixed $i$. Now $A_n(i)$ is (up to sign) the $i$th elementary symmetric function of the roots. Hence $|q_1^{(n)}|$ is about $2^n$. Then $|q_2^{(n)}|$ is about $(3/2)^n$, $|q_3^{(n)}|$ is about $(4/3)^n$, etc. It is not hard to show in fact that for fixed $i$, $$\lim_{n\to\infty} |q_i^{(n)}|^{1/n} = \frac{i+1}{i}.$$ Note also that there is an explicit formula for $A_n(i)$ as a sum with $i+2$ terms (https://en.wikipedia.org/wiki/Eulerian_number). Thus any rational symmetric function of the roots can be written in terms of these sums.


text:
Computing The Sum of a Geometric Series Examples 1

# Computing The Sum of a Geometric Series Examples 1

Recall from the Computing The Sum of a Geometric Series page that a series in the form $\sum_{n=1}^{\infty} ar^{n-1}$ is a geometric series, and $\sum_{n=1}^{\infty} ar^{n-1} = \frac{a}{1 - r}$ if $\mid r \mid < 1$ and diverges if $\mid r \mid ≥ 1$.

We will now look at some more examples involving geometric series.

## Example 1

Find the sum of the series $\sum_{n=1}^{\infty} 3 \left ( \frac{1}{6} \right )^{n-1}$.

We note that $r = \frac{1}{6}$ and $\biggr \rvert \frac{1}{6} \biggr \rvert < 1$, so this series converges and:

(1)
\begin{align} \quad \sum_{n=1}^{\infty} 3 \left ( \frac{1}{6} \right )^{n-1} = \frac{3}{1 - \frac{1}{6}} = \frac{18}{5} \end{align}

## Example 2

Find the sum of the series $\sum_{n=0}^{\infty} -2 \left ( \frac{1}{3} \right)^n$.

Notice that this series can be rewritten as $\sum_{n=1}^{\infty} -2 \left ( \frac{1}{3} \right)^{n-1}$, and so $r = \frac{1}{3}$ and $\biggr \rvert \frac{1}{3} \biggr \rvert < 1$ so this series converges and:

(2)
\begin{align} \quad \sum_{n=0}^{\infty} -2 \left ( \frac{1}{3} \right)^n = \frac{-2}{1 - \frac{1}{3}} = -3 \end{align}

## Example 3

Find the sum of the series $\sum_{n=-4}^{\infty} \left ( \frac{2}{3} \right )^{2n}$.

We will first rewrite this series by removing the squared power, and so:

(3)
\begin{align} \quad \sum_{n=-4}^{\infty} \left ( \frac{2}{3} \right )^{2n} = \sum_{n=-4}^{\infty} \left ( \left ( \frac{2}{3} \right )^2 \right )^{n} = \sum_{n=-4}^{\infty} \left ( \frac{4}{9} \right )^{n} \end{align}

We now want the power $n - 1$ attached to the fraction in the summation. We can achieve this by changing the start index of the sum:

(4)
\begin{align} \sum_{n=-4}^{\infty} \left ( \frac{4}{9} \right )^{n} = \sum_{n=-3}^{\infty} \left ( \frac{4}{9} \right )^{n-1} \end{align}

Now we need the start index to be at $1$, and so we will compute the first few terms of the series, that is:

(5)
\begin{align} \quad \sum_{n=-3}^{\infty} \left ( \frac{4}{9} \right )^{n-1} = \left ( \frac{4}{9} \right)^{-4} + \left ( \frac{4}{9} \right)^{-3} + \left ( \frac{4}{9} \right)^{-2} + \left ( \frac{4}{9} \right)^{-1} + \sum_{n=1}^{\infty} \left ( \frac{4}{9} \right )^{n-1} \end{align}

Now the remaining summation is a geometric series and $\sum_{n=1}^{\infty} \left ( \frac{4}{9} \right )^{n-1} = \frac{1}{1 - \frac{4}{9}} = \frac{9}{5}$, and so:

(6)
\begin{align} \quad \sum_{n=-3}^{\infty} \left ( \frac{4}{9} \right )^{n-1} = \left ( \frac{4}{9} \right)^{-4} + \left ( \frac{4}{9} \right)^{-3} + \left ( \frac{4}{9} \right)^{-2} + \left ( \frac{4}{9} \right)^{-1} + \frac{9}{5} \\ \quad \sum_{n=-3}^{\infty} \left ( \frac{4}{9} \right )^{n-1} = \frac{6561}{256} + \frac{729}{64} + \frac{81}{16} + \frac{9}{4} + \frac{9}{5} = 46 + \frac{169}{1280} \end{align}

## Example 4

Find the sum of the series $\sum_{n=-2}^{\infty} \left [ \left ( \frac{1}{2} \right )^n - \left ( \frac{1}{3} \right) ^{2n} \right ]$.

Let's first split this series into two simpler series:

(7)
\begin{align} \quad \sum_{n=-2}^{\infty} \left [ \left ( \frac{1}{2} \right )^n - \left ( \frac{1}{3} \right) ^{2n} \right ] = \sum_{n=-2}^{\infty} \left ( \frac{1}{2} \right )^n - \sum_{n=-2}^{\infty} \left ( \frac{1}{3} \right )^{2n} = \sum_{n=-2}^{\infty} \left ( \frac{1}{2} \right )^n - \sum_{n=-2}^{\infty} \left ( \frac{1}{9} \right )^{n} \end{align}

We want the exponents in both of these series to be $n - 1$ so we will change the start indices:

(8)
\begin{align} \quad \sum_{n=-2}^{\infty} \left ( \frac{1}{2} \right )^n - \sum_{n=-2}^{\infty} \left ( \frac{1}{9} \right )^{n} = \sum_{n=-1}^{\infty} \left ( \frac{1}{2} \right )^{n-1} - \sum_{n=-1}^{\infty} \left ( \frac{1}{9} \right )^{n-1} \end{align}

Now we want the start indices to be $1$, so we will compute the first few terms of each series:

(9)
\begin{align} \quad \sum_{n=-1}^{\infty} \left ( \frac{1}{2} \right )^{n-1} - \sum_{n=-1}^{\infty} \left ( \frac{1}{9} \right )^{n-1} = \left [ \left ( \frac{1}{2} \right )^{-2} + \left ( \frac{1}{2} \right )^{-1} + \sum_{n=1}^{\infty} \left ( \frac{1}{2} \right )^{n-1} \right ] - \left [ \left ( \frac{1}{9} \right )^{-2} + \left ( \frac{1}{9} \right )^{-1} + \sum_{n=1}^{\infty} \left ( \frac{1}{9} \right )^{n-1} \right ] \\ \quad \sum_{n=-1}^{\infty} \left ( \frac{1}{2} \right )^{n-1} - \sum_{n=-1}^{\infty} \left ( \frac{1}{9} \right )^{n-1} = 4 +2 + \frac{1}{1 - \frac{1}{2}} - 81 - 9 - \frac{1}{1 - \frac{1}{9}} \\ \quad \sum_{n=-1}^{\infty} \left ( \frac{1}{2} \right )^{n-1} - \sum_{n=-1}^{\infty} \left ( \frac{1}{9} \right )^{n-1} = 4 +2 + 2 - 81 - 9 - \frac{9}{8} = -82 - \frac{9}{8} = -\frac{665}{8} \\ \end{align}


text:
Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

September 17, 2019
September 17, 2019
Press Releases
September 17, 2019
Games Press

If you enjoy reading this site, you might also want to check out these UBM Tech sites:

# Unity Addressables: It's never too big to fit

by Ruben Torres Bonet on 09/04/19 10:40:00 am

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

You are leading a team of programmers and also supporting artists to port a good-looking PS4 VR game to Oculus Quest. You have one month to halve your memory budget and 6 months to complete it. What's your first move? Let's bring Unity Addressables to the table.

You do realize you have to tackle quite many challenging tasks at once. I bet some might be personally more concerning than others, depending on your expertise level in each area. If you had to pick one that robbed your sacred sleep the most, which one would it be?

My initial guess would be this: above 70% of the readers would say CPU/GPU performance is the biggest concern when porting a title to Quest. And to that I say: you can very well be right. Performance is one of the toughest areas to improve on in a VR game. For optimizations of this kind, you require in-depth knowledge about the product, which is a time intensive process. Sometimes you even cannot just optimize further, which usually ends in dropping expensive gameplay or graphics features. And not meeting people's expectations is a dangerous place to be.

Performance, performance, performance.. The word might let some chills go down your spine. What can you expect in this regard from the Quest platform? How does it perform? The thing is, if you have had some development experience in it, you will probably know that in spite of being mobile hardware, it is astonishingly powerful.

But Ruben! Don't give me that crap. I tell you my phone slows down significantly the time I open a second browser tab. How dare you say mobile platforms can be so performant?

I read your mind, didn't I? The massive difference lies on Quest's active cooling system, which gives it a huge boost on its attainable CPU/GPU hardware levels that no other mobile platform can offer. It is a powerful fan that will prevent your hair from gathering dust and avoid melting the CPU together with your face (the GoT crown scene comes to mind).

Additionally and on the side of the Quest software, the more specialized OS is better optimized for virtual reality rendering (surprise) than the generic Android variant. Mobile hardware has been catching up with standalone platforms so quickly in the last few years.

But, at the same time, I cannot deny that our task of constantly rendering at 72 fps will prove to be challenging, especially for VR ports coming from high-end platforms. To be more precise, when we talk about the Oculus Quest, you have to picture yourself a Snapdragon 835 with a screen, a battery, four cameras and a fan.

What could look like a disadvantage can actually be thought of as an edge. This mobile platform is a well researched piece of s*** hardware. One can say there are a myriad of known tricks you can pull off to quickly reduce the CPU and GPU load up to an acceptable point. If it is of your interest, you will be able to read about it in upcoming posts. As of now, we will take performance out of the equation for this post.

What might catch your attention in our challenge is that, compared to the PS4, there is a single hardware characteristic literally halved on the Quest: the RAM capacity. That's right, we go from 8 to 4GB RAM. This is an approximation since, in both platforms, the operating system does not allow you to use it all so it can keep track of a few subsystems for the ecosystem to work. On the Quest you will be able to roughly use up to 2.2 GB of RAM before things get messy.

Ruben, what do you exactly mean by messy? The thing is, proper memory handling is crucial for your game. This is so because you have two constraints:

• Hard memory constraint: if you go above a certain threshold, the OS will just kill your game
• Soft memory constraint: above another certain limit, the OS might decide to kill your game when your user minimizes your game, takes the headset off or you go out of the Oculus Guardian area

Obviously, you do not want any of the two to happen in your game. Can you picture an angry player who just lost his last two hours of gameplay? Yes, they will go to your store and nothing pretty will come out of their mouth.

Angry player - RUN!

The thing is, the guaranteed availability of 2.2GB of RAM is not much, honestly. It's usually not a problem for new projects where you track your stats constantly from the beginning, but it definitely is an issue for a port to a severely downgraded hardware.

If you dealt with similar ports in the past, you will quickly realize how extremely challenging it can become to decrease your game's RAM budget by half. It grandly depends on how well the game architecture was prepared for such a change, but in most cases this will temporally transform you into a tear-producing machine.

The most popular strategies to reduce memory pressure include tweaking asset compression settings, optimizing scripts, reducing shader variants, etc.. Depending on the specifics of your project, tweaking texture import settings is your first go-to solution, but if you need to you can also resort to compressing meshes, animations and audio. The problem is that those techniques are usually complex in nature and will have a ceiling limit.

Not all platforms support the same import settings; targeting several devices will dramatically increase your build pipeline overhead, not to mention QA, art, design and programming complexity. Does this Android device support ASTC, or just ETC2 (if at all)? Oh, we also want to build 64 bit builds, but also keep the players on the 32 bit versions. How many split-APKs should we create, and worse, manage and test, for each update we do on the game? You want to make your life easier, so you should not rely exclusively on these techniques.

We would like to go further. As usual, we want to keep things as simple as possible (TM), especially if you are doing a port. Redesigning the entire game for performance's sake is a worse option than just not porting it. For that matter and in today’s topic, I will offer you one of the biggest gains for the buck: I will show you how to halve a project's memory budget in matter of hours. Boom!

Wouldn't that be awesome?

Go ahead, go ahead... ask me: is it really possible for me? The answer is: it depends on your starting point, but in my experience, YES. Unity Addressables can be of a great value here. The catch? You must be willing to put in the work and to master the process. But this workflow will earn you the title of employee of the month.

If you are interested, keep reading.

In this post you and I will go through the journey of moving from a traditional asset management to an addressables-based asset management system. To illustrate the process,  we will port a simplified old-school project to the new era of Unity Addressables.

Now, you might ask me: why don't you just show me the real-life work you did?

In a non-competitive world I would just show you all the material I created. In the real world though, that is likely to get me canned. And worse, busted.

What I will do instead is to offer you my guidance so you and I iterate on project that absolutely represents the difficulties you could find tomorrow in your next project. And we will do so by first welcoming Unity's Addressables to our family of suggested packages.

In this blog post I will get you started in Addressables ASAP so you can implement your own Unity Addressables system in a matter of minutes.

Time to pay attention to this very important section. Our goal is to diagnose easy memory gains and implement them fast. There are several ways to do this, but one of the most powerful yet simplest methods to pick the low-hanging fruits by loading the initial scene and opening up the profiler. Why this?

Because an unoptimized game architecture can frequently be diagnosed at any point during gameplay, so the quickest way to check this is by profiling the initial scenes. The reason for this is the common over-usage of singleton-like scripts containing references to every single asset in the project just in case you need it.

In order words, in many games there is usually an almighty script causing an asset reference hellThis component keeps each asset loaded at all times independently from whether it's used or not at that time point.

It depends. If your game is likely to be constrained by memory capacity, it is a very risky solution, as your game will not scale with the amount of assets you add (e.g. think of future DLCs). If you target heterogeneous devices, such as Android, you don't have a single memory budget; each device will offer a different one, so you settle for the worst case. The OS can decide to kill your app at any point if our user decides to answer a quick message in Facebook. Then the user comes back and surprise, all their game is gone for good.

How fun is that?

Zero. Unless you are overworked and sleep deprived, situation which might grant you a desperation laugh.

To complicate matters further, if later on you decide (or someone decides for you) to port your game to another less powerful platform while keeping cross-play working, good luck. You don't want to get caught in the middle of this technical challenge.

On the other side, is there a situation where this traditional asset management solution works just fine? The answer is yes. If you are developing it for a homogeneous platform such as PS4 and most requirements are set from the beginning, the benefits of global objects can potentially outweigh the extra added complexity of a better memory management system.

Because let's face it: a plain, good old global object containing everything you need is a simple solution, if it works well enough for you. It will simplify your code and will also preload all your referenced assets.

In any case, the traditional memory management approach is not acceptable for developers seeking to push the boundaries of the hardware. And as you are reading this, I take you want to level up your skills. So it is time for just doing that.

## Unity Addressables: Requirements for our project

If you are planning on just reading this blog entry, your screen will suffice. Otherwise, if you want to do this along with me, you will need:

• Functional hands
• Overclocked brain
• Unity 2019.2.0f1 or similar
• The level 1 project from GitHub (download zip or through command line)

The git repository will contain three commits, one per skill level-up section in the blog (unless I messed up at some point, case in which I will commit a fix).

Download the project in ZIP format directly from GitHub. Or alternatively, visit the GitHub Repository

## Level 1 developer: Traditional asset management

We are starting here with the simplest asset management method here. In our case, this entails having a list of direct references to skybox materials in our component.

If you are doing this with me, the setup is a simple 3 step process:

2. Open the project in Unity
3. Hit the damn play button!

Good, good. You can click a few buttons and change the skybox. This is so original... and boring. I take it, no Unity Addressables yet.

In a short moment you and I will see why we need to endure this short-lasting boredom.

To start with, how is our project structured? It pivots around two main systems. On the one side, we have our SkyboxManager game object. This component is the main script holding the references to the skybox materials and switches between them based on UI events. Easy enough.

using UnityEngine;

public class SkyboxManager : MonoBehaviour
{
[SerializeField] private Material[] _skyboxMaterials;

public void SetSkybox(int skyboxIndex)
{
RenderSettings.skybox = _skyboxMaterials[skyboxIndex];
}
}

The SkyboxManager offers the UI system a function to apply a specific material to the scene settings through the usage of the RenderSettings API.

Secondly, we have our CanvasSkyboxSelector. This game object contains a canvas component, rendering a a collection of vertically-distributed buttons. Each button, when clicked, will invoke the aforementioned Manager function to swap the rendered skybox based on the button id. Put in another way, each button's OnClick event calls the SetSkybox function on the Manager. Isn't that simple?

Once we're done daydreaming how immersive it was to play X2, it's time to get our hands dirty. Let's launch the multisensory experience and open the profiler (ctrl/cmd + 7; or Window - Analysis - Profiler). I take you are familiar with this tool, otherwise you know what to do with the top record button. After a few seconds of recording, stop it and see the metrics for yourself: CPU, memory, etc.. Anything of interest?

Performance is pretty good, which is nothing surprising considering the scope of the project. You could literally turn this project into a VR experience and I assure you that your users will not fill any of the bile buckets that so many players filled when playing Eve: Valkyrie.

In our case, we will be focusing on the memory section. The simple view mode will display something as depicted below:

Level 1 Asset Management - Simple Memory Profiling

The numbers on the texture size look pretty oversized for just displaying a single skybox at any given time, don't you agree? Surprise incoming: this is the pattern you will find in many unoptimized projects you are likely to suffer lead. But heck, in this case it's just a collection of skyboxes. In others, it will be more about characters, planets, sounds, music. You name it, I have it.

Time for magic. Let's switch the memory profiler to detail mode. Have a look!

Level 1 Asset Management - Detailed Memory Profiling

Holy crap, what happened there? All skybox textures are loaded in memory, but only one is displayed at any given time. You see what we did? This rookie architecture produced the whoooooooping figure of 400mb.

This is definitely a no-go, considering this is just a small piece of a future game. Addressing this very problem is the foundation for our next section.

Come with me!

Summary:

• Traditional asset management entails direct references
• Therefore you keep all objects loaded at all times
• Your project will not scale this way

## Level 2 developer: Unity Addressables workflow(s)

In video- games you start at level 1, which is great, but once you know the gameplay rules it is time to leave the safe city walls in our quest to level up. That is exactly what this section is about.

Download the project in ZIP format directly from GitHub. Or alternatively, visit the GitHub Repository

As we previously saw in the profiler, we have all skyboxes loaded in memory even though only one is actively used. That is not a scalable solution, as at some point you will be limited on the amount of different variations of assets you can offer to your players. An advice? Don't limit the fun of your players.

Here, let me help you. Take my shovel so we can dig the so needed tunnel to escape the prison of traditional asset management. Let's add a new fancy tool to our toolbox: the API of Unity Addressables.

The first thing we need to do is to install the Addressables package. For that, go to Window → Package Manager, as shown below:

Unity Package Manager - Unity Addressables

Once installed, it's time to mark the materials as addressables. Select them and activate the addressables flag in the inspector window.

Level 2 Asset Management (Unity Addressables)

What this will do is to ask Unity politely to include those materials and their texture dependencies in the addressables database. This database will be used during our builds to pack the assets in chunks that can easily be loaded at any point during in our game.

I'll show you something cool now. Open Window → Asset Management → Addressables. Guess what's that? It's our database screaming to go live!

Level 2 Asset Management (Unity Addressables) - Main Window

My dear reader: that was the easy part. Now comes the fun part.

I want you to pay a visit to an old friend of ours from the previous section: Sir SkyboxManager. If you check it, you will notice it is still holding direct references to our assets! We don't want that.

We are teaching our manager to use indirect references instead - i.e. AssetReference (in Unreal Engine you might know them as soft references).

Let us do just that, let's beautify our component:

using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;

public class SkyboxManager : MonoBehaviour
{
[SerializeField] private List<AssetReference> _skyboxMaterials;

private AsyncOperationHandle  _currentSkyboxMaterialOperationHandle;

public void SetSkybox(int skyboxIndex)
{
StartCoroutine(SetSkyboxInternal(skyboxIndex));
}

private IEnumerator SetSkyboxInternal(int skyboxIndex)
{
if (_currentSkyboxMaterialOperationHandle.IsValid())
{
}

var skyboxMaterialReference = _skyboxMaterials[skyboxIndex];
yield return _currentSkyboxMaterialOperationHandle;
RenderSettings.skybox = _currentSkyboxMaterialOperationHandle.Result;
}
}

What happens here is the following:

• A major change happens in line 7, where we hold a list of indirect references (AssetReference) instead of direct material references. This change is key, because these materials will NOT be loaded automatically just by being referenced. Their loading will have to be made explicit. Afterwards, please reassign the field in the editor.
• Line 13: since we are now in an asynchronous workflow, we favor the use of a coroutine. We simply start a new coroutine that will handle the skybox material change.
• We check in lines 18-20 whether we have an existing handle to a skybox material and, if so, we release the skybox we were previously rendering.  Every time we do such a load operation with the Addressables API, we receive a handle we should store for future operations. A handle is just a data structure containing data relevant to the management of a specific addressable asset.
• We resolve specific addressable reference to a skybox material in line 23 and then you call its LoadAssetAsync function, over which you can yield (line 25) so we wait for this operation to finish before proceeding further. Thanks to the usage of generics, there's no need for sucky casts. Neat!
• Finally, once the material and its dependencies have been loaded, we proceed to change the skybox of the scene in line 26. The material will be offered in the Result field that belongs to the handle we used to load it.

Level 2 Asset Management (Unity Addressables) - AssetReference list

Keep in mind: this code is not production-ready. Do not use it when programming an airplane. I decided to favor simplicity over robustness to keep the matter simple enough.

Enough with explanations. It is time you and I saw this in action.

If you would be so kind to perform the following steps:

1. In the Addressables window, cook the content (build player content)
2. Then make a build on a platform of your choice
3. Run it and connect the (memory) profiler to it.
4. Protect your jaw from dropping.

Level 2 (Unity Addressables) - Build Player Content

Level 2 Asset Management (Unity Addressables) - Memory Profiler

Isn't asset cooking delicious?

I like happy profilers. And what you saw is the happiest profiler the world has ever seen. A satisfied profiler will mean several things. For one, it means happy players playing your game in a Nokia 3210. It also means happy producers. And as of you, it means a happy wallet.

This is the power of the Addressables system.

Addressables which comes with little overhead on the team. On the one side, programmers will have to support asynchronous workflows (easy-peasy with Coroutines). Also, designers will have to learn the possibilities of the system, e.g. addressable groups, and gather experience to make intelligent decisions. Finally, IT will be delighted to set up an infrastructure to deliver the assets over the network, if you opt to host them online.

I have to congratulate you. Let me tell you what we have accomplished:

• Appropriate memory management.
• Faster install times, reduced in-store app size.
• Higher device compatibility.
• Asynchronous architecture.
• Opening the door of storing this content online → decoupling data from code.

I would be proud of such a gain. It's for sure a good return on investment.

Oh, and make sure to mention your experience with Addressables in job interviews.

To avoid an excessively long article, you may check out the following extended content on the website of The Gamedev Guru's Blog:

• INTERMEDIATE: Instancing and reference counting.

Summary:

• Addressables-based asset management scales just well
• Do not forget to cook content on changes or you'll give your game a pinkish tint!

Level 3 Asset Management (??) - Content Network Delivery

## Level 3 developer: The Guru's way for Unity Addressables

In the previous section, we achieved the biggest bang for the buck. We leveled up our skills by moving from a traditional asset management system to an addressables-based workflow. This is a huge win for your project, as a small time investment gave your project the room to better scale in assets while keeping your memory usage low. That accomplishment indeed made you step up to level 2, congrats! However, one question is yet to answer:

Is that it?

No. We barely scratched the surface of Addressables, there are further ways to improve your project with this game-changer package.

Of course you do not have to memorize all the details regarding Addressables, but I highly suggest you to have an overview of them because down the road you are likely to encounter further challenges and you will be thankful to have read a bit further. That's why I prepared an extra short guide for you.

There you will learn about the following aspects:

• The Addressables window: the details matter
• Network delivery: reduce the time-to-play user experience
• Build pipeline integration
• Practical strategies: speed up your workflow, trash your 10-minute coffee breaks

And more importantly, answer questions such as:

• What is the hidden meaning behind Send Profiler Events?
• How useful is the AddressableAssetSettings API?
• How do I integrate this all with the BuildPlayerWindow API?
• What's the difference between Fast ModeVirtual Mode and Packed Mode?

In order to grab the level 3 guide check out my blog post on The Gamedev Guru's Blog.

## Conclusions

At the beginning of the post I presented you the challenge I had: halving the memory budget of the project being developed for Oculus Quest in just a month. The result? Task accomplished.

This is what I have to say about this almighty Unity package: the Addressables system saved my butt. It made the timed task possible by avoiding a massive game redesign; those are nearly impossible to pull off in the setting of our port.

Addressables is a promising system. On the one hand, Unity developers are working hard to improve it further. On the other hand, it is production ready and documentation is available.

This means: you can start today using it in your projects. If you followed the article and the guide, it should take you little time to get it running in your project.

Consider it a medium-term investment. You will invest some time this week in order to gain it back during the upcoming months/years of your project. Not only you will benefit from it, but more players will be able to play your game due to supporting more devices.

I really hope this was entertaining and useful for you, feel free to visit The Gamedev Guru's Blog for more content.

Let me know what you think

### Related Jobs

Daybreak Games — Austin, Texas, United States
[09.16.19]

Senior Engine Programmer
Daybreak Games — Austin, Texas, United States
[09.16.19]

Senior Server Programmer
Daybreak Games — Austin, Texas, United States
[09.16.19]

Senior Tools Programmer
Disbelief — Cambridge, Massachusetts, United States
[09.16.19]

Senior Programmer, Cambridge, MA